enh(chore): package perl dependencies (cpan / net-curl / libssh-session ...) (#4755)

This commit is contained in:
hamzabessa 2023-12-07 09:45:34 +01:00 committed by GitHub
parent 831f8591be
commit dd7f18da99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 12408 additions and 6 deletions

114
.github/actions/package-nfpm/action.yml vendored Normal file
View File

@ -0,0 +1,114 @@
name: package-nfpm
description: Package module using nfpm
inputs:
nfpm_file_pattern:
description: The pattern of the nfpm configuration file(s)
required: true
package_extension:
description: The package extension (deb or rpm)
required: true
distrib:
description: The package distrib
required: true
major_version:
description: The major version
required: false
minor_version:
description: The minor version
required: false
release:
description: The package release number
required: false
arch:
description: The package architecture
required: false
commit_hash:
description: The commit hash
required: true
cache_key:
description: The package files cache key
required: true
rpm_gpg_key:
description: The rpm gpg key
required: true
rpm_gpg_signing_key_id:
description: The rpm gpg signing key identifier
required: true
rpm_gpg_signing_passphrase:
description: The rpm gpg signing passphrase
required: true
runs:
using: composite
steps:
- name: Import gpg key
env:
RPM_GPG_SIGNING_KEY: ${{ inputs.rpm_gpg_key }}
run: echo -n "$RPM_GPG_SIGNING_KEY" > key.gpg
shell: bash
- name: Build ${{ inputs.package_extension }} files
env:
RPM_GPG_SIGNING_KEY_ID: ${{ inputs.rpm_gpg_signing_key_id }}
RPM_GPG_SIGNING_PASSPHRASE: ${{ inputs.rpm_gpg_signing_passphrase }}
run: |
export MAJOR_VERSION="${{ inputs.major_version }}"
export VERSION="${{ inputs.major_version }}.${{ inputs.minor_version }}"
export RELEASE="${{ inputs.release }}"
export ARCH="${{ inputs.arch }}"
if [ "${{ inputs.package_extension }}" = "rpm" ]; then
export DIST=".${{ inputs.distrib }}"
export APACHE_USER="apache"
export APACHE_GROUP="apache"
else
export DIST=""
export APACHE_USER="www-data"
export APACHE_GROUP="www-data"
fi
MAJOR_LEFT=$( echo $MAJOR_VERSION | cut -d "." -f1 )
MAJOR_RIGHT=$( echo $MAJOR_VERSION | cut -d "-" -f1 | cut -d "." -f2 )
BUMP_MAJOR_RIGHT=$(( MAJOR_RIGHT_PART + 1 ))
if [ "$MAJOR_RIGHT" = "04" ]; then
BUMP_MAJOR_LEFT="$MAJOR_LEFT"
BUMP_MAJOR_RIGHT="10"
else
BUMP_MAJOR_LEFT=$(( $MAJOR_LEFT + 1 ))
BUMP_MAJOR_RIGHT="04"
fi
export NEXT_MAJOR_VERSION="$BUMP_MAJOR_LEFT.$BUMP_MAJOR_RIGHT"
export RPM_SIGNING_KEY_FILE="$(pwd)/key.gpg"
export RPM_SIGNING_KEY_ID="$RPM_GPG_SIGNING_KEY_ID"
export NFPM_RPM_PASSPHRASE="$RPM_GPG_SIGNING_PASSPHRASE"
for FILE in ${{ inputs.nfpm_file_pattern }}; do
DIRNAME=$(dirname $FILE)
BASENAME=$(basename $FILE)
cd $DIRNAME
sed -i "s/@APACHE_USER@/$APACHE_USER/g" $BASENAME
sed -i "s/@APACHE_GROUP@/$APACHE_GROUP/g" $BASENAME
sed -i "s/@COMMIT_HASH@/${{ inputs.commit_hash }}/g" $BASENAME
nfpm package --config $BASENAME --packager ${{ inputs.package_extension }}
cd -
mv $DIRNAME/*.${{ inputs.package_extension }} ./
done
shell: bash
- name: Cache packages
uses: actions/cache/save@v3
with:
path: ./*.${{ inputs.package_extension }}
key: ${{ inputs.cache_key }}
# Update if condition to true to get packages as artifacts
- if: ${{ false }}
name: Upload package artifacts
uses: actions/upload-artifact@v3
with:
name: packages-${{ inputs.distrib }}
path: ./*.${{ inputs.package_extension}}
retention-days: 1

View File

@ -0,0 +1,85 @@
name: "promote testing to stable"
description: "Promote testing packages to stable."
inputs:
artifactory_token:
description: "Artifactory token"
required: true
module:
description: "Module"
required: true
distrib:
description: "The distribution used for packaging"
required: true
stability:
description: "The package stability (stable, testing, unstable)"
required: true
runs:
using: "composite"
steps:
- uses: jfrog/setup-jfrog-cli@v3
env:
JF_URL: https://centreon.jfrog.io
JF_ACCESS_TOKEN: ${{ inputs.artifactory_token }}
- name: Promote RPM packages to stable
if: ${{ startsWith(inputs.distrib, 'el') }}
run: |
set -x
echo "[DEBUG] - Distrib: ${{ inputs.distrib }}"
for ARCH in "noarch" "x86_64"; do
echo "[DEBUG] - Get path of $ARCH testing artifacts to promote to stable."
SRC_PATHS=$(jf rt s --include-dirs rpm-plugins/${{ inputs.distrib }}/testing/$ARCH/${{ inputs.module }}/*.rpm | jq -r '.[].path')
if [[ ${SRC_PATHS[@]} ]]; then
for SRC_PATH in ${SRC_PATHS[@]}; do
echo "[DEBUG] - Source path found: $SRC_PATH"
done
else
echo "[DEBUG] - No source path found."
continue
fi
echo "[DEBUG] - Build $ARCH target path."
TARGET_PATH="rpm-plugins/${{ inputs.distrib }}/${{ inputs.stability }}/$ARCH/RPMS/${{ inputs.module }}/"
echo "[DEBUG] - Target path: $TARGET_PATH"
echo "[DEBUG] - Promoting $ARCH testing artifacts to stable."
for ARTIFACT in ${SRC_PATHS[@]}; do
echo "[DEBUG] - Promoting $ARTIFACT to stable."
jf rt cp $ARTIFACT $TARGET_PATH --flat=true
done
done
shell: bash
- name: Promote DEB package to stable
if: ${{ startsWith(inputs.distrib, 'bullseye') }}
run: |
echo "[DEBUG] - Distrib: ${{ inputs.distrib }}"
echo "[DEBUG] - Get path of testing DEB packages to promote to stable."
SRC_PATHS=$(jf rt s --include-dirs apt-plugins-testing/pool/${{ inputs.module }}/*.deb | jq -r '.[].path')
if [[ ${SRC_PATHS[@]} ]]; then
for SRC_PATH in ${SRC_PATHS[@]}; do
echo "[DEBUG] - Source path found: $SRC_PATH"
done
else
echo "[DEBUG] - No source path found."
continue
fi
echo "[DEBUG] - Build target path."
TARGET_PATH="apt-plugins-${{ inputs.stability }}/pool/${{ inputs.module }}/"
echo "[DEBUG] - Target path: $TARGET_PATH"
echo "[DEBUG] - Promoting DEB testing artifacts to stable."
for ARTIFACT in ${SRC_PATHS[@]}; do
echo "[DEBUG] - Promoting $ARTIFACT to stable."
jf rt cp $ARTIFACT $TARGET_PATH --flat=true
done
shell: bash

View File

@ -19,13 +19,27 @@ on:
jobs:
create-and-push-docker:
runs-on: ubuntu-22.04
strategy:
matrix:
distrib: [centos7, alma8, alma9, bullseye]
include:
- project: plugins
- runner: ubuntu-22.04
dockerfile: packaging-plugins-centos7
image: packaging-plugins-centos7
- runner: ubuntu-22.04
dockerfile: packaging-plugins-alma8
image: packaging-plugins-alma8
- runner: ubuntu-22.04
dockerfile: packaging-plugins-alma9
image: packaging-plugins-alma9
- runner: ubuntu-22.04
dockerfile: packaging-plugins-bullseye
image: packaging-plugins-bullseye
- runner: ["self-hosted", "collect-arm64"]
dockerfile: packaging-plugins-bullseye
image: packaging-plugins-bullseye-arm64
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
@ -48,9 +62,9 @@ jobs:
- uses: docker/build-push-action@v3
with:
file: .github/docker/Dockerfile.packaging-${{ matrix.project }}-${{ matrix.distrib }}
file: .github/docker/Dockerfile.${{ matrix.dockerfile }}
context: .
build-args: "REGISTRY_URL=${{ vars.DOCKER_PROXY_REGISTRY_URL }}"
pull: true
push: true
tags: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/packaging-${{ matrix.project }}-${{ matrix.distrib }}:latest
tags: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest

View File

@ -0,0 +1,375 @@
name: perl-cpan-libraries
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- ".github/workflows/perl-cpan-libraries.yml"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- ".github/workflows/perl-cpan-libraries.yml"
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package:
needs: [get-environment]
if: ${{ needs.get-environment.outputs.stability != 'stable' }}
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
distrib: [el8, el9, bullseye]
name:
[
"Authen::SASL::SASLprep",
"Authen::SCRAM::Client",
"boolean",
"BSON",
"BSON::XS",
"Carp::Assert",
"Clone",
"Clone::Choose",
"common::sense",
"Convert::Binary::C",
"Convert::EBCDIC",
"Crypt::Blowfish_PP",
"DateTime::Format::Duration::ISO8601",
"DBD::Sybase",
"Device::Modbus",
"Device::Modbus::RTU::Client",
"Device::Modbus::TCP::Client",
"Digest::MD5::File",
"Digest::SHA1",
"Email::Send::SMTP::Gmail",
"EV",
"FFI::CheckLib",
"FFI::Platypus",
"File::SearchPath",
"Hash::Merge",
"Hash::Ordered",
"HTTP::Daemon",
"HTTP::Daemon::SSL",
"HTTP::ProxyPAC",
"JMX::Jmx4Perl",
"JSON::Parse",
"JSON::WebToken",
"LV",
"MIME::Types",
"MongoDB",
"Net::DHCP",
"Net::FTPSSL",
"Net::HTTPTunnel",
"Net::NTP",
"Net::SMTPS",
"Net::SMTP_auth",
"Net::Subnet",
"Net::TFTP",
"PBKDF2::Tiny",
"Schedule::Cron",
"Statistics::Descriptive",
"Statistics::Regression",
"Sys::SigAction",
"Term::Clui",
"Term::ShellUI",
"Unicode::Stringprep",
"URI::Encode",
"URI::Template",
"URL::Encode",
"UUID",
"UUID::URandom",
"WWW::Selenium",
"XML::Filter::BufferText",
"XML::LibXML::Simple",
"XML::SAX::Writer",
"ZMQ::Constants",
"ZMQ::FFI",
"ZMQ::LibZMQ4"
]
include:
- build_distribs: "el8,el9,bullseye"
- rpm_dependencies: ""
- deb_dependencies: ""
- rpm_provides: ""
- version: ""
- use_dh_make_perl: "true"
- spec_file: ""
- distrib: el8
package_extension: rpm
image: packaging-plugins-alma8
- distrib: el9
package_extension: rpm
image: packaging-plugins-alma9
- distrib: bullseye
package_extension: deb
image: packaging-plugins-bullseye
- name: "BSON"
build_distribs: "el8,el9"
rpm_provides: "perl(BSON::Bytes) perl(BSON::Code) perl(BSON::DBRef) perl(BSON::OID) perl(BSON::Raw) perl(BSON::Regex) perl(BSON::Time) perl(BSON::Timestamp) perl(BSON::Types) perl(BSON)"
- name: "BSON::XS"
build_distribs: "el8,el9"
- name: "Convert::Binary::C"
build_distribs: "el8,el9"
- name: "DateTime::Format::Duration::ISO8601"
rpm_provides: "perl(DateTime-Format-Duration-ISO8601)"
- name: "DBD::Sybase"
build_distribs: "el8,el9"
- name: "Device::Modbus::RTU::Client"
version: "0.022"
- name: "Device::Modbus::TCP::Client"
version: "0.026"
- name: "EV"
build_distribs: "el8,el9"
- name: "FFI::CheckLib"
build_distribs: "el8,el9"
- name: "FFI::Platypus"
build_distribs: "el8,el9"
rpm_provides: "perl(FFI::Platypus::Buffer) perl(FFI::Platypus::Memory)"
- name: "Net::DHCP"
rpm_provides: "perl(Net::DHCP::Constants) perl(Net::DHCP::Packet)"
- name: "Statistics::Regression"
version: "0.53"
- name: "UUID"
use_dh_make_perl: "false"
- name: "ZMQ::Constants"
build_distribs: "el9,bullseye"
- name: "ZMQ::FFI"
build_distribs: "el8,el9"
rpm_dependencies: "zeromq"
- name: "ZMQ::LibZMQ4"
use_dh_make_perl: "false"
version: "0.01"
rpm_dependencies: "zeromq"
deb_dependencies: "libzmq5"
name: package ${{ matrix.distrib }} ${{ matrix.name }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- uses: actions/checkout@v4
- if: ${{ contains(matrix.build_distribs, matrix.distrib) && matrix.package_extension == 'rpm' }}
run: |
yum install -y yum-utils epel-release git
yum config-manager --set-enabled crb || true # alma 9
yum config-manager --set-enabled powertools || true # alma 8
yum install -y cpanminus rpm-build libcurl-devel libssh-devel expat-devel gcc ruby libuuid-devel zeromq-devel libxml2-devel libffi-devel perl-DBI perl-Net-Pcap freetds freetds-devel
shell: bash
- if: ${{ contains(matrix.build_distribs, matrix.distrib) && matrix.package_extension == 'rpm' && matrix.spec_file == '' }}
run: |
if [ -z "${{ matrix.version }}" ]; then
PACKAGE_VERSION=""
else
PACKAGE_VERSION=" -v ${{ matrix.version }}"
fi
if [ -z "${{ matrix.rpm_dependencies }}" ]; then
PACKAGE_DEPENDENCIES=""
else
for PACKAGE_DEPENDENCY in `echo ${{ matrix.rpm_dependencies }}`; do
PACKAGE_DEPENDENCIES="$PACKAGE_DEPENDENCIES --depends $PACKAGE_DEPENDENCY"
done
fi
if [ -z "${{ matrix.rpm_provides }}" ]; then
PACKAGE_PROVIDES=""
else
for PACKAGE_PROVIDE in `echo "${{ matrix.rpm_provides }}"`; do
PACKAGE_PROVIDES="$PACKAGE_PROVIDES --provides $PACKAGE_PROVIDE"
done
fi
cpanm Module::Build::Tiny
cpanm Module::Install
export SYBASE="/usr"
gem install fpm
fpm -s cpan -t ${{ matrix.package_extension }} --rpm-dist ${{ matrix.distrib }} --verbose --cpan-verbose --no-cpan-test$PACKAGE_DEPENDENCIES$PACKAGE_PROVIDES$PACKAGE_VERSION ${{ matrix.name }}
shell: bash
- if: ${{ contains(matrix.build_distribs, matrix.distrib) && matrix.package_extension == 'rpm' && matrix.spec_file != '' }}
run: |
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
rpmbuild --undefine=_disable_source_fetch -ba ${{ matrix.spec_file }}
cp -r ~/rpmbuild/RPMS/noarch/*.rpm .
shell: bash
- if: ${{ contains(matrix.build_distribs, matrix.distrib) && matrix.package_extension == 'deb' && matrix.use_dh_make_perl == 'false' }}
run: |
apt update
apt install -y cpanminus ruby libcurl4-openssl-dev libssh-dev uuid-dev libczmq-dev
PACKAGE_NAME=`echo ${{ matrix.name }} | sed -e 's/::/-/g' | tr '[A-Z]' '[a-z]' | sed -e 's/^/lib/g' | sed -e 's/$/-perl/g' | sed -e 's/liblib/lib/g'`
if [ -z "${{ matrix.version }}" ]; then
PACKAGE_VERSION=""
else
PACKAGE_VERSION=" -v ${{ matrix.version }}"
fi
if [ -z "${{ matrix.deb_dependencies }}" ]; then
PACKAGE_DEPENDENCIES=""
else
for PACKAGE_DEPENDENCY in `echo ${{ matrix.deb_dependencies }}`; do
PACKAGE_DEPENDENCIES="$PACKAGE_DEPENDENCIES --depends $PACKAGE_DEPENDENCY"
done
fi
cpanm Module::Build::Tiny
cpanm Module::Install
gem install fpm
fpm -s cpan -t ${{ matrix.package_extension }} --deb-dist ${{ matrix.distrib }} --verbose --cpan-verbose --no-cpan-test -n $PACKAGE_NAME$PACKAGE_DEPENDENCIES$PACKAGE_VERSION ${{ matrix.name }}
shell: bash
- if: ${{ contains(matrix.build_distribs, matrix.distrib) && matrix.package_extension == 'deb' && matrix.use_dh_make_perl == 'true' }}
run: |
apt update
apt install -y cpanminus libcurl4-openssl-dev dh-make-perl libssh-dev uuid-dev libczmq-dev libmodule-install-perl
if [ -z "${{ matrix.version }}" ]; then
PACKAGE_VERSION=""
else
PACKAGE_VERSION="--version ${{ matrix.version }}-${{ matrix.distrib }}"
fi
DEB_BUILD_OPTIONS="nocheck nodocs notest" dh-make-perl make --build $PACKAGE_VERSION --cpan ${{ matrix.name }}
shell: bash
- uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.package_extension }}-${{ matrix.distrib }}
path: ./*.${{ matrix.package_extension }}
retention-days: 1
sign-rpm:
needs: [package]
runs-on: ubuntu-22.04
strategy:
matrix:
distrib: [el8, el9]
name: sign rpm ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/rpm-signing:ubuntu
options: -t
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- run: apt-get install -y zstd
shell: bash
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
with:
name: packages-rpm-${{ matrix.distrib }}
path: ./
- run: echo "HOME=/root" >> $GITHUB_ENV
shell: bash
- run: rpmsign --addsign ./*.rpm
shell: bash
- uses: actions/cache@v3
with:
path: ./*.rpm
key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
download-and-cache-deb:
needs: [package]
runs-on: ubuntu-22.04
steps:
- uses: actions/download-artifact@v3
with:
name: packages-deb-bullseye
path: ./
- uses: actions/cache@v3
with:
path: ./*.deb
key: ${{ github.sha }}-${{ github.run_id }}-deb-bullseye
deliver-rpm:
needs: [get-environment, sign-rpm]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: perl-cpan-libraries
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}
deliver-deb:
needs: [get-environment, download-and-cache-deb]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [bullseye]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/deb-delivery
with:
module_name: perl-cpan-libraries
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: ${{ github.sha }}-${{ github.run_id }}-deb-${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9, bullseye]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: perl-cpan-libraries
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

205
.github/workflows/perl-crypt-argon2.yml vendored Normal file
View File

@ -0,0 +1,205 @@
name: perl-crypt-argon2
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- "dependencies/perl-crypt-argon2/**"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- "dependencies/perl-crypt-argon2/**"
tags:
- perl-crypt-argon2-*
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package:
needs: [get-environment]
strategy:
fail-fast: false
matrix:
include:
- image: packaging-plugins-alma8
distrib: el8
package_extension: rpm
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-alma9
distrib: el9
package_extension: rpm
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-bullseye
distrib: bullseye
package_extension: deb
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-bullseye-arm64
distrib: bullseye
package_extension: deb
runner: ["self-hosted", "collect-arm64"]
arch: arm64
runs-on: ${{ matrix.runner }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
name: package ${{ matrix.distrib }} ${{ matrix.arch }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install locally Crypt::Argon2
run: |
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
apt-get update
apt-get install -y cpanminus gcc
else
dnf install -y cpanminus gcc
fi
cpanm -v -l /tmp Crypt::Argon2@0.019
shell: bash
- name: Set package name and paths according to distrib
run: |
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
NAME="libcrypt-argon2-perl"
if [ "${{ matrix.arch }}" = "amd64" ]; then
PERL_VENDORARCH="/usr/lib/x86_64-linux-gnu/perl5/5.32"
else
PERL_VENDORARCH="/usr/lib/aarch64-linux-gnu/perl5/5.32"
fi
else
NAME="perl-Crypt-Argon2"
if [ "${{ matrix.distrib }}" = "el8" ]; then
PERL_VENDORARCH="/usr/local/lib64/perl5"
else
PERL_VENDORARCH="/usr/local/lib64/perl5/5.32"
fi
fi
sed -i "s/@NAME@/$NAME/g" dependencies/perl-crypt-argon2/perl-crypt-argon2.yaml
sed -i "s#@PERL_VENDORARCH@#$PERL_VENDORARCH#g" dependencies/perl-crypt-argon2/perl-crypt-argon2.yaml
cat dependencies/perl-crypt-argon2/perl-crypt-argon2.yaml
shell: bash
- name: Package
uses: ./.github/actions/package-nfpm
with:
nfpm_file_pattern: "dependencies/perl-crypt-argon2/perl-crypt-argon2.yaml"
distrib: ${{ matrix.distrib }}
package_extension: ${{ matrix.package_extension }}
arch: ${{ matrix.arch }}
commit_hash: ${{ github.sha }}
cache_key: cache-${{ github.sha }}-${{ matrix.package_extension}}-perl-crypt-argon2-${{ matrix.distrib }}-${{ matrix.arch }}-${{ github.head_ref || github.ref_name }}
rpm_gpg_key: ${{ secrets.RPM_GPG_SIGNING_KEY }}
rpm_gpg_signing_key_id: ${{ secrets.RPM_GPG_SIGNING_KEY_ID }}
rpm_gpg_signing_passphrase: ${{ secrets.RPM_GPG_SIGNING_PASSPHRASE }}
# set condition to true if artifacts are needed
- if: ${{ false }}
name: Upload package artifacts
uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.distrib }}-${{ matrix.arch }}
path: ./*.${{ matrix.package_extension}}
retention-days: 1
deliver-rpm:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
name: Deliver ${{ matrix.distrib }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: perl-crypt-argon2-amd64
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-rpm-perl-crypt-argon2-${{ matrix.distrib }}-amd64-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
deliver-deb:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
include:
- distrib: bullseye
arch: amd64
- distrib: bullseye
arch: arm64
name: Deliver ${{ matrix.distrib }} ${{ matrix.arch }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/deb-delivery
with:
module_name: perl-crypt-argon2-${{ matrix.arch }}
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-deb-perl-crypt-argon2-${{ matrix.distrib }}-${{ matrix.arch }}-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
include:
- distrib: el8
arch: amd64
- distrib: el9
arch: amd64
- distrib: bullseye
arch: amd64
- distrib: bullseye
arch: arm64
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} ${{ matrix.arch }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: perl-crypt-argon2-${{ matrix.arch }}
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

View File

@ -0,0 +1,208 @@
name: perl-filesys-smbclient
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- "dependencies/perl-filesys-smbclient/**"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- "dependencies/perl-filesys-smbclient/**"
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package-rpm:
needs: [get-environment]
if: ${{ needs.get-environment.outputs.stability != 'stable' }}
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: packaging-plugins-alma8
distrib: el8
- image: packaging-plugins-alma9
distrib: el9
name: package ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- uses: actions/checkout@v4
- run: |
yum install -y yum-utils
yum config-manager --set-enabled crb || true # alma 9
yum config-manager --set-enabled powertools || true # alma 8
yum install -y libsmbclient-devel make gcc perl perl-devel perl-ExtUtils-MakeMaker
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
cp -rp dependencies/perl-filesys-smbclient/src perl-Filesys-SmbClient/
tar czf ~/rpmbuild/SOURCES/perl-Filesys-SmbClient.tar.gz perl-Filesys-SmbClient
rpmbuild -ba dependencies/perl-filesys-smbclient/packaging/rpm/perl-Filesys-SmbClient.spec
cp -r ~/rpmbuild/RPMS/x86_64/*.rpm .
shell: bash
- uses: actions/cache@v3
with:
path: ./*.rpm
key: unsigned-${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
sign-rpm:
needs: [package-rpm]
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: packaging-alma8
distrib: el8
- image: packaging-alma9
distrib: el9
name: sign rpm ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/rpm-signing:ubuntu
options: -t
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- run: |
apt-get update
apt-get install -y zstd
shell: bash
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: ./*.rpm
key: unsigned-${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
- run: echo "HOME=/root" >> $GITHUB_ENV
shell: bash
- run: rpmsign --addsign ./*.rpm
shell: bash
- uses: actions/cache@v3
with:
path: ./*.rpm
key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
package-deb:
needs: [get-environment]
if: ${{ needs.get-environment.outputs.stability != 'stable' }}
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: packaging-plugins-bullseye
distrib: bullseye
name: package ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- uses: actions/checkout@v4
- run: |
apt update
apt install -y dh-make-perl perl libsmbclient-dev
mv dependencies/perl-filesys-smbclient/src/ perl-filesys-smbclient
tar czf perl-filesys-smbclient.tar.gz perl-filesys-smbclient
DEB_BUILD_OPTIONS="nocheck nodocs notest noautodbgsym" dh-make-perl make --verbose --build --version 4.0-${{ matrix.distrib }} perl-filesys-smbclient/
shell: bash
- uses: actions/cache@v3
with:
path: ./*.deb
key: ${{ github.sha }}-${{ github.run_id }}-deb-${{ matrix.distrib }}
deliver-rpm:
needs: [get-environment, sign-rpm]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: perl-filesys-smbclient
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}
deliver-deb:
needs: [get-environment, package-deb]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [bullseye]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/deb-delivery
with:
module_name: perl-filesys-smbclient
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: ${{ github.sha }}-${{ github.run_id }}-deb-${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9, bullseye]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: perl-filesys-smbclient
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

184
.github/workflows/perl-json-path.yml vendored Normal file
View File

@ -0,0 +1,184 @@
name: perl-json-path
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- "dependencies/perl-json-path/**"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- "dependencies/perl-json-path/**"
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package:
needs: [get-environment]
strategy:
fail-fast: false
matrix:
include:
- image: packaging-plugins-alma8
distrib: el8
package_extension: rpm
- image: packaging-plugins-alma9
distrib: el9
package_extension: rpm
- image: packaging-plugins-bullseye
distrib: bullseye
package_extension: deb
runs-on: ubuntu-22.04
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
name: package ${{ matrix.distrib }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install locally JSON::Path
run: |
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
apt-get update
apt-get install -y cpanminus gcc
else
dnf install -y cpanminus gcc
fi
if [ "${{ matrix.distrib }}" = "el8" ]; then
cpanm -v -l /tmp JSON::Path@0.5
else
cpanm -v -l /tmp JSON::Path@1.0.3
fi
shell: bash
- name: Set package name and paths according to distrib
run: |
VERSION="1.0.3"
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
NAME="libjson-path-perl"
PERL_VENDORLIB="/usr/share/perl5"
else
NAME="perl-JSON-Path"
if [ "${{ matrix.distrib }}" = "el8" ]; then
VERSION="0.5" # https://github.com/centreon/centreon-plugins/issues/4540
PERL_VENDORLIB="/usr/local/share/perl5"
else
PERL_VENDORLIB="/usr/local/share/perl5/5.32"
fi
fi
sed -i "s/@NAME@/$NAME/g" dependencies/perl-json-path/perl-json-path.yaml
sed -i "s/@VERSION@/$VERSION/g" dependencies/perl-json-path/perl-json-path.yaml
sed -i "s#@PERL_VENDORLIB@#$PERL_VENDORLIB#g" dependencies/perl-json-path/perl-json-path.yaml
cat dependencies/perl-json-path/perl-json-path.yaml
shell: bash
- name: Package
uses: ./.github/actions/package-nfpm
with:
nfpm_file_pattern: "dependencies/perl-json-path/perl-json-path.yaml"
distrib: ${{ matrix.distrib }}
package_extension: ${{ matrix.package_extension }}
arch: all
commit_hash: ${{ github.sha }}
cache_key: cache-${{ github.sha }}-${{ matrix.package_extension}}-perl-json-path-${{ matrix.distrib }}-${{ github.head_ref || github.ref_name }}
rpm_gpg_key: ${{ secrets.RPM_GPG_SIGNING_KEY }}
rpm_gpg_signing_key_id: ${{ secrets.RPM_GPG_SIGNING_KEY_ID }}
rpm_gpg_signing_passphrase: ${{ secrets.RPM_GPG_SIGNING_PASSPHRASE }}
# set condition to true if artifacts are needed
- if: ${{ false }}
name: Upload package artifacts
uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.distrib }}
path: ./*.${{ matrix.package_extension}}
retention-days: 1
deliver-rpm:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
name: Deliver ${{ matrix.distrib }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: perl-json-path
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-rpm-perl-json-path-${{ matrix.distrib }}-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
deliver-deb:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [bullseye]
name: Deliver ${{ matrix.distrib }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/deb-delivery
with:
module_name: perl-json-path
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-deb-perl-json-path-${{ matrix.distrib }}-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [bullseye]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: perl-json-path
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

View File

@ -0,0 +1,216 @@
name: perl-keepass-reader
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- "dependencies/perl-keepass-reader/**"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- "dependencies/perl-keepass-reader/**"
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package-rpm:
needs: [get-environment]
if: ${{ needs.get-environment.outputs.stability != 'stable' }}
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: packaging-plugins-alma8
distrib: el8
- image: packaging-plugins-alma9
distrib: el9
name: package ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- uses: actions/checkout@v4
- run: |
yum install -y make perl perl-devel perl-ExtUtils-MakeMaker
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
cp -rp dependencies/perl-keepass-reader/src perl-KeePass-Reader/
tar czf ~/rpmbuild/SOURCES/perl-KeePass-Reader.tar.gz perl-KeePass-Reader
rpmbuild -ba dependencies/perl-keepass-reader/packaging/rpm/perl-KeePass-Reader.spec
cp -r ~/rpmbuild/RPMS/noarch/*.rpm .
shell: bash
- uses: actions/cache@v3
with:
path: ./*.rpm
key: unsigned-${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
sign-rpm:
needs: [package-rpm]
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: packaging-alma8
distrib: el8
- image: packaging-alma9
distrib: el9
name: sign rpm ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/rpm-signing:ubuntu
options: -t
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- run: |
apt-get update
apt-get install -y zstd
shell: bash
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: ./*.rpm
key: unsigned-${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
- run: echo "HOME=/root" >> $GITHUB_ENV
shell: bash
- run: rpmsign --addsign ./*.rpm
shell: bash
- uses: actions/cache@v3
with:
path: ./*.rpm
key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
- uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.distrib }}
path: ./*.rpm
retention-days: 1
package-deb:
needs: [get-environment]
if: ${{ needs.get-environment.outputs.stability != 'stable' }}
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: bullseye
distrib: bullseye
name: package ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/packaging-plugins-${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- uses: actions/checkout@v4
- run: |
apt update
apt install -y dh-make-perl perl
mv dependencies/perl-keepass-reader/src/ perl-keepass-reader
tar czf perl-keepass-reader.tar.gz perl-keepass-reader
DEB_BUILD_OPTIONS="nocheck nodocs notest noautodbgsym" dh-make-perl make -p libkeepass-reader-perl --verbose --build --version 0.2-${{ matrix.distrib }} perl-keepass-reader/
shell: bash
- uses: actions/cache@v3
with:
path: ./*.deb
key: ${{ github.sha }}-${{ github.run_id }}-deb-${{ matrix.distrib }}
- uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.distrib }}
path: ./*.deb
retention-days: 1
deliver-rpm:
needs: [get-environment, sign-rpm]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: perl-keepass-reader
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}
deliver-deb:
needs: [get-environment, package-deb]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [bullseye]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/deb-delivery
with:
module_name: perl-keepass-reader
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: ${{ github.sha }}-${{ github.run_id }}-deb-${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9, bullseye]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: perl-keepass-reader
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

View File

@ -0,0 +1,203 @@
name: perl-libssh-session
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- "dependencies/perl-libssh-session/**"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- "dependencies/perl-libssh-session/**"
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package:
needs: [get-environment]
strategy:
fail-fast: false
matrix:
include:
- image: packaging-plugins-alma8
distrib: el8
package_extension: rpm
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-alma9
distrib: el9
package_extension: rpm
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-bullseye
distrib: bullseye
package_extension: deb
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-bullseye-arm64
distrib: bullseye
package_extension: deb
runner: ["self-hosted", "collect-arm64"]
arch: arm64
runs-on: ${{ matrix.runner }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
name: package ${{ matrix.distrib }} ${{ matrix.arch }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install locally Libssh::Session
run: |
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
apt-get update
apt-get install -y cpanminus gcc libssh-dev
else
dnf install -y cpanminus gcc libssh-devel
fi
cpanm -v -l /tmp Libssh::Session@0.8
shell: bash
- name: Set package name and paths according to distrib
run: |
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
NAME="libssh-session-perl"
if [ "${{ matrix.arch }}" = "amd64" ]; then
PERL_VENDORARCH="/usr/lib/x86_64-linux-gnu/perl5/5.32"
else
PERL_VENDORARCH="/usr/lib/aarch64-linux-gnu/perl5/5.32"
fi
else
NAME="perl-Libssh-Session"
if [ "${{ matrix.distrib }}" = "el8" ]; then
PERL_VENDORARCH="/usr/local/lib64/perl5"
else
PERL_VENDORARCH="/usr/local/lib64/perl5/5.32"
fi
fi
sed -i "s/@NAME@/$NAME/g" dependencies/perl-libssh-session/perl-libssh-session.yaml
sed -i "s#@PERL_VENDORARCH@#$PERL_VENDORARCH#g" dependencies/perl-libssh-session/perl-libssh-session.yaml
cat dependencies/perl-libssh-session/perl-libssh-session.yaml
shell: bash
- name: Package
uses: ./.github/actions/package-nfpm
with:
nfpm_file_pattern: "dependencies/perl-libssh-session/perl-libssh-session.yaml"
distrib: ${{ matrix.distrib }}
package_extension: ${{ matrix.package_extension }}
arch: ${{ matrix.arch }}
commit_hash: ${{ github.sha }}
cache_key: cache-${{ github.sha }}-${{ matrix.package_extension}}-perl-libssh-session-${{ matrix.distrib }}-${{ matrix.arch }}-${{ github.head_ref || github.ref_name }}
rpm_gpg_key: ${{ secrets.RPM_GPG_SIGNING_KEY }}
rpm_gpg_signing_key_id: ${{ secrets.RPM_GPG_SIGNING_KEY_ID }}
rpm_gpg_signing_passphrase: ${{ secrets.RPM_GPG_SIGNING_PASSPHRASE }}
# set condition to true if artifacts are needed
- if: ${{ false }}
name: Upload package artifacts
uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.distrib }}-${{ matrix.arch }}
path: ./*.${{ matrix.package_extension}}
retention-days: 1
deliver-rpm:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
name: Deliver ${{ matrix.distrib }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: perl-libssh-session-amd64
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-rpm-perl-libssh-session-${{ matrix.distrib }}-amd64-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
deliver-deb:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
include:
- distrib: bullseye
arch: amd64
- distrib: bullseye
arch: arm64
name: Deliver ${{ matrix.distrib }} ${{ matrix.arch }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/deb-delivery
with:
module_name: perl-libssh-session-${{ matrix.arch }}
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-deb-perl-libssh-session-${{ matrix.distrib }}-${{ matrix.arch }}-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
include:
- distrib: el8
arch: amd64
- distrib: el9
arch: amd64
- distrib: bullseye
arch: amd64
- distrib: bullseye
arch: arm64
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} ${{ matrix.arch }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: perl-libssh-session-${{ matrix.arch }}
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

203
.github/workflows/perl-net-curl.yml vendored Normal file
View File

@ -0,0 +1,203 @@
name: perl-net-curl
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- "dependencies/perl-net-curl/**"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- "dependencies/perl-net-curl/**"
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package:
needs: [get-environment]
strategy:
fail-fast: false
matrix:
include:
- image: packaging-plugins-alma8
distrib: el8
package_extension: rpm
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-alma9
distrib: el9
package_extension: rpm
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-bullseye
distrib: bullseye
package_extension: deb
runner: ubuntu-22.04
arch: amd64
- image: packaging-plugins-bullseye-arm64
distrib: bullseye
package_extension: deb
runner: ["self-hosted", "collect-arm64"]
arch: arm64
runs-on: ${{ matrix.runner }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
name: package ${{ matrix.distrib }} ${{ matrix.arch }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install locally Net::Curl
run: |
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
apt-get update
apt-get install -y libcurl4-openssl-dev cpanminus gcc
else
dnf install -y libcurl-devel cpanminus gcc
fi
cpanm -v -l /tmp Net::Curl@0.54
shell: bash
- name: Set package name and paths according to distrib
run: |
if [ "${{ matrix.distrib }}" = "bullseye" ]; then
NAME="libnet-curl-perl"
if [ "${{ matrix.arch }}" = "amd64" ]; then
PERL_VENDORARCH="/usr/lib/x86_64-linux-gnu/perl5/5.32"
else
PERL_VENDORARCH="/usr/lib/aarch64-linux-gnu/perl5/5.32"
fi
else
NAME="perl-Net-Curl"
if [ "${{ matrix.distrib }}" = "el8" ]; then
PERL_VENDORARCH="/usr/local/lib64/perl5"
else
PERL_VENDORARCH="/usr/local/lib64/perl5/5.32"
fi
fi
sed -i "s/@NAME@/$NAME/g" dependencies/perl-net-curl/perl-net-curl.yaml
sed -i "s#@PERL_VENDORARCH@#$PERL_VENDORARCH#g" dependencies/perl-net-curl/perl-net-curl.yaml
cat dependencies/perl-net-curl/perl-net-curl.yaml
shell: bash
- name: Package
uses: ./.github/actions/package-nfpm
with:
nfpm_file_pattern: "dependencies/perl-net-curl/perl-net-curl.yaml"
distrib: ${{ matrix.distrib }}
package_extension: ${{ matrix.package_extension }}
arch: ${{ matrix.arch }}
commit_hash: ${{ github.sha }}
cache_key: cache-${{ github.sha }}-${{ matrix.package_extension}}-perl-net-curl-${{ matrix.distrib }}-${{ matrix.arch }}-${{ github.head_ref || github.ref_name }}
rpm_gpg_key: ${{ secrets.RPM_GPG_SIGNING_KEY }}
rpm_gpg_signing_key_id: ${{ secrets.RPM_GPG_SIGNING_KEY_ID }}
rpm_gpg_signing_passphrase: ${{ secrets.RPM_GPG_SIGNING_PASSPHRASE }}
# set condition to true if artifacts are needed
- if: ${{ false }}
name: Upload package artifacts
uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.distrib }}-${{ matrix.arch }}
path: ./*.${{ matrix.package_extension}}
retention-days: 1
deliver-rpm:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
name: Deliver ${{ matrix.distrib }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: perl-net-curl-amd64
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-rpm-perl-net-curl-${{ matrix.distrib }}-amd64-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
deliver-deb:
needs: [get-environment, package]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
include:
- distrib: bullseye
arch: amd64
- distrib: bullseye
arch: arm64
name: Deliver ${{ matrix.distrib }} ${{ matrix.arch }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/deb-delivery
with:
module_name: perl-net-curl-${{ matrix.arch }}
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: cache-${{ github.sha }}-deb-perl-net-curl-${{ matrix.distrib }}-${{ matrix.arch }}-${{ github.head_ref || github.ref_name }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
include:
- distrib: el8
arch: amd64
- distrib: el9
arch: amd64
- distrib: bullseye
arch: amd64
- distrib: bullseye
arch: arm64
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} ${{ matrix.arch }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: perl-net-curl-${{ matrix.arch }}
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

151
.github/workflows/plink.yml vendored Normal file
View File

@ -0,0 +1,151 @@
name: plink
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
paths:
- "dependencies/plink/**"
push:
branches:
- develop
- dev-[2-9][0-9].[0-9][0-9].x
- master
- "[2-9][0-9].[0-9][0-9].x"
paths:
- ".github/workflows/plink.yml"
jobs:
get-environment:
uses: ./.github/workflows/get-environment.yml
package-rpm:
needs: [get-environment]
if: ${{ needs.get-environment.outputs.stability != 'stable' }}
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: packaging-plugins-alma8
distrib: el8
- image: packaging-plugins-alma9
distrib: el9
name: package ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/${{ matrix.image }}:latest
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- uses: actions/checkout@v4
- run: |
yum install -y wget gcc make
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
wget -P ~/rpmbuild/SOURCES/ https://the.earth.li/~sgtatham/putty/0.74/putty-0.74.tar.gz
rpmbuild -ba dependencies/plink/packaging/rpm/plink.spec
cp -r ~/rpmbuild/RPMS/x86_64/*.rpm .
shell: bash
- uses: actions/cache@v3
with:
path: ./*.rpm
key: unsigned-${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
sign-rpm:
needs: [package-rpm]
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- image: packaging-alma8
distrib: el8
- image: packaging-alma9
distrib: el9
name: sign rpm ${{ matrix.distrib }}
container:
image: ${{ vars.DOCKER_INTERNAL_REGISTRY_URL }}/rpm-signing:ubuntu
options: -t
credentials:
username: ${{ secrets.DOCKER_REGISTRY_ID }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWD }}
steps:
- run: |
apt-get update
apt-get install -y zstd
shell: bash
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: ./*.rpm
key: unsigned-${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
- run: echo "HOME=/root" >> $GITHUB_ENV
shell: bash
- run: rpmsign --addsign ./*.rpm
shell: bash
- uses: actions/cache@v3
with:
path: ./*.rpm
key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
- uses: actions/upload-artifact@v3
with:
name: packages-${{ matrix.distrib }}
path: ./*.rpm
retention-days: 1
deliver-rpm:
needs: [get-environment, sign-rpm]
if: ${{ contains(fromJson('["testing", "unstable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Delivery
uses: ./.github/actions/rpm-delivery
with:
module_name: plink
distrib: ${{ matrix.distrib }}
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
cache_key: ${{ github.sha }}-${{ github.run_id }}-rpm-${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}
promote:
needs: [get-environment]
if: ${{ contains(fromJson('["stable"]'), needs.get-environment.outputs.stability) }}
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el8, el9]
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Promote ${{ matrix.distrib }} to stable
uses: ./.github/actions/promote-to-stable
with:
artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
module: plink
distrib: ${{ matrix.distrib }}
stability: ${{ needs.get-environment.outputs.stability }}

View File

@ -0,0 +1,77 @@
name: "@NAME@"
arch: "${ARCH}"
platform: "linux"
version_schema: "none"
version: "0.019"
release: "2${DIST}"
section: "default"
priority: "optional"
maintainer: "Centreon <contact@centreon.com>"
description: |
This module implements the Argon2 key derivation function, which is suitable to convert any password into a cryptographic key.
This is most often used to for secure storage of passwords but can also be used to derive a encryption key from a password.
It offers variable time and memory costs as well as output size.
Commit: @COMMIT_HASH@
vendor: "Centreon"
homepage: "https://www.centreon.com"
license: "Apache-2.0"
contents:
- src: "/tmp/bin/argon2-calibrate"
dst: "/usr/local/bin/"
file_info:
mode: 0755
packager: rpm
- src: "/tmp/bin/argon2-calibrate"
dst: "/usr/bin/"
file_info:
mode: 0755
packager: deb
- src: "/tmp/lib/perl5/*/auto/Crypt/Argon2/"
dst: "@PERL_VENDORARCH@/auto/Crypt/Argon2/"
file_info:
mode: 0644
- src: "/tmp/lib/perl5/*/Crypt/Argon2.pm"
dst: "@PERL_VENDORARCH@/Crypt/"
file_info:
mode: 0644
- src: "/tmp/man/man3/Crypt::Argon2*"
dst: "/usr/share/man/man3/"
file_info:
mode: 0644
overrides:
rpm:
depends:
- perl(Exporter)
- perl(Time::HiRes)
- perl(XSLoader)
- perl(strict)
- perl(warnings)
conflicts:
- perl-Crypt-Argon2-debuginfo
replaces:
- perl-Crypt-Argon2-debuginfo
provides:
- perl-Crypt-Argon2-debuginfo
- perl(Crypt::Argon2)
deb:
depends:
- perl
- libc6
conflicts:
- libcrypt-argon2-perl-dbgsym
replaces:
- libcrypt-argon2-perl-dbgsym
provides:
- libcrypt-argon2-perl-dbgsym
rpm:
summary: Perl interface to the Argon2 key derivation functions
compression: zstd
signature:
key_file: ${RPM_SIGNING_KEY_FILE}
key_id: ${RPM_SIGNING_KEY_ID}

View File

@ -0,0 +1,49 @@
Name: perl-Filesys-SmbClient
Version: 4.0
Release: 1%{?dist}
Summary: perl interface to access Samba filesystem with libsmclient.so
Group: Development/Libraries
License: Apache
URL: https://github.com/garnier-quentin/Filesys-SmbClient
Source0: %{name}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: libsmbclient-devel
BuildRequires: make
BuildRequires: gcc
BuildRequires: perl-ExtUtils-MakeMaker
Provides: perl(Filesys::SmbClient)
Requires: libsmbclient
AutoReqProv: no
%description
Provide interface to access routine defined in libsmbclient.so provided with Samba.
%prep
%setup -q -n %{name}
%build
%{__perl} Makefile.PL INSTALLDIRS=vendor OPTIMIZE="$RPM_OPT_FLAGS"
make %{?_smp_mflags}
%install
rm -rf %{buildroot}
make pure_install PERL_INSTALL_ROOT=$RPM_BUILD_ROOT
find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type f -name '*.bs' -a -size 0 -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type d -depth -exec rmdir {} 2>/dev/null ';'
%{_fixperms} $RPM_BUILD_ROOT/*
%check
#make test
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{perl_vendorarch}/
%{_mandir}/man3/*.3*
%changelog

View File

@ -0,0 +1,20 @@
# git
\B\.git\b
\B\.gitignore\b
# build files
^blib
^_build
^Build$
^cover_db
^Makefile(\.old)?$
^MANIFEST\.
^pm_to_blib$
# contrib
^contrib
# temporary
~$
\.bak$
\.old$

View File

@ -0,0 +1,13 @@
use 5.008005;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'Filesys::SmbClient',
VERSION_FROM => 'SmbClient.pm',
PREREQ_PM => { 'Test::More' => 0 },
ABSTRACT_FROM => 'SmbClient.pm',
AUTHOR => 'Quentin Garnier',
LIBS => ['-lsmbclient'],
DEFINE => '',
INC => '-I.',
OBJECT => 'libauthSamba.o SmbClient.o',
);

View File

@ -0,0 +1,865 @@
package Filesys::SmbClient;
# module Filesys::SmbClient : provide function to access Samba filesystem
# with libsmclient.so
# Copyright 2000-2012 A.Barbet alian@cpan.org. All rights reserved.
# $Log: SmbClient.pm,v $
# Revision 4.0 compatible samba4 only
#
# Revision 3.2 2012/12/04 14:49:32 alian
#
# release 3.2: implements connection close with smbc_free_context (acca@cpan.org)
#
# release 3.1: fix for rt#12221 rt#18757 rt#13173 and bug in configure
#
# Revision 3.0 2005/03/04 16:15:00 alian
# 3.0 2005/03/05 alian
# - Update to samba3 API and use SMBCTXX
# - Add set_flag method for samba 3.0.11
# - Update smb2www-2.cgi to browse workgroup with smb://
# - Return 0 not undef at end of file with read/READLINE
# (tks to jonathan.segal at genizon.com for report).
# - Fix whence bug in seek method (not used before)
# - Add some tests for read and seek patched in this version
#
# Revision 1.5 2003/11/09 18:28:01 alian
# Add Copyright section
#
# See file CHANGES for others update
use strict;
use constant SMBC_WORKGROUP => 1;
use constant SMBC_SERVER => 2;
use constant SMBC_FILE_SHARE => 3;
use constant SMBC_PRINTER_SHARE => 4;
use constant SMBC_COMMS_SHARE => 5;
use constant SMBC_IPC_SHARE =>6;
use constant SMBC_DIR => 7;
use constant SMBC_FILE => 8;
use constant SMBC_LINK => 9;
use constant MAX_LENGTH_LINE => 4096;
use vars qw($AUTOLOAD $VERSION @ISA @EXPORT);
require Exporter;
require DynaLoader;
require AutoLoader;
use POSIX 'SEEK_SET';
use Tie::Handle;
my $DEBUG = 0;
@ISA = qw(Exporter DynaLoader Tie::Handle);
@EXPORT = qw(SMBC_DIR SMBC_WORKGROUP SMBC_SERVER SMBC_FILE_SHARE
SMBC_PRINTER_SHARE SMBC_COMMS_SHARE SMBC_IPC_SHARE SMBC_FILE
SMBC_LINK _write _open _close _read _lseek);
$VERSION = ('$Revision: 4.0 $ ' =~ /(\d+\.\d+)/)[0];
bootstrap Filesys::SmbClient $VERSION;
my %commandes =
(
"close" => \&_close,
"closedir" => \&_closedir,
"fstat" => \&_fstat,
"opendir" => \&_opendir,
"print_file" => \&_print_file,
"stat" => \&_stat,
"rename" => \&_rename,
"rmdir" => \&_rmdir,
"unlink" => \&_unlink,
"unlink_print_job" => \&_unlink_print_job,
);
#------------------------------------------------------------------------------
# AUTOLOAD
#------------------------------------------------------------------------------
sub AUTOLOAD {
my $self =shift;
my $attr = $AUTOLOAD;
$attr =~ s/.*:://;
return unless $attr =~ /[^A-Z]/;
die "Method undef ->$attr()\n" unless defined($commandes{$attr});
return $commandes{$attr}->($self->{context}, @_);
}
#------------------------------------------------------------------------------
# TIEHANDLE
#------------------------------------------------------------------------------
sub TIEHANDLE {
require 5.005_64;
my ($class,$fn,$mode,@args) = @_;
$mode = '0666' if (!$mode);
my $self = new($class, @args);
print "Filesys::SmbClient TIEHANDLE\n" if ($DEBUG);
if ($fn) {
$self->{FD} = _open($self->{context}, $fn, $mode) or return undef; }
return $self;
}
#------------------------------------------------------------------------------
# OPEN
#------------------------------------------------------------------------------
sub OPEN {
my ($class,$fn,$mode) = @_;
$mode = '0666' if (!$mode);
print "OPEN\n" if ($DEBUG);
$class->{FD} = _open($class->{context}, $fn, $mode) or return undef;
$class;
}
#------------------------------------------------------------------------------
# FILENO
#------------------------------------------------------------------------------
sub FILENO {
my $class = shift;
return $class->{FD};
}
#------------------------------------------------------------------------------
# WRITE
#------------------------------------------------------------------------------
sub WRITE {
my ($self,$buffer,$length,$offset) = @_;
print "Filesys::SmbClient WRITE\n" if ($DEBUG);
$buffer = substr($buffer,0,$length) if ($length);
SEEK($self,$offset, SEEK_SET) if ($offset);
my $lg = _write($self->{context}, $self->{FD}, $buffer, $length);
return ($lg == -1) ? undef : $lg;
}
#------------------------------------------------------------------------------
# SEEK
#------------------------------------------------------------------------------
sub SEEK {
my ($self,$offset,$whence) = @_;
print "Filesys::SmbClient SEEK\n" if ($DEBUG);
return _lseek($self->{context}, $self->{FD}, $offset, $whence);
}
#------------------------------------------------------------------------------
# READ
#------------------------------------------------------------------------------
sub READ {
my $self = shift;
print "Filesys::SmbClient READ\n" if ($DEBUG);
my $buf = \$_[0];
my $lg = ($_[1] ? $_[1] : MAX_LENGTH_LINE);
#
defined($$buf = _read($self->{context}, $self->{FD}, $lg)) or return undef;
# $$buf = _read($self->{context}, $self->{FD}, $lg) or return undef;
return length($$buf);
}
#------------------------------------------------------------------------------
# READLINE
#------------------------------------------------------------------------------
sub READLINE {
my $self = shift;
print "Filesys::SmbClient READLINE\n" if ($DEBUG);
# Check if we have \n on old string
my $buf = $self->{_BUFFER};
if ($buf && $buf=~m!^([^\n]*\n)(.*)$!ms) {
print "Gave ->$1<- and take ->$2<-\n" if ($self->{params}->{debug});
my $p = $1;
$self->{_BUFFER} = $2;
return wantarray() ? ($p,$self->READLINE) : $p;
}
# Read while we haven't \n or eof
my $part;
READ($self,$part,MAX_LENGTH_LINE);
while ($part and $part!~m!\n!ms and $self->{_FD}) {
$buf.=$part;
$part = $self->read($self->{_FD}, @_);
}
$buf.= $part if ($part);
# eof
return (wantarray() ? "" : undef) if (!$buf);
# Return first line and save rest in $self->{_BUFFER}
if ($buf=~m!^([^\n]*\n)(.*)$!ms) {
print "Give ->$1<- and take ->$2<-\n" if ($self->{params}->{debug});
$self->{_BUFFER} = $2;
return wantarray() ? ($1,$self->READLINE) : $1;
}
undef $self->{_BUFFER};
return wantarray() ? ($buf,$self->READLINE) : $buf;
}
#------------------------------------------------------------------------------
# GETC
#------------------------------------------------------------------------------
sub GETC {
my $self = shift;
my $c;
print "Filesys::SmbClient GETC\n" if ($DEBUG);
if ($self->{_BUFFER}) {
print "Filesys::SmbClient GETC using $self->{_BUFFER}\n"
if ($self->{params}->{debug});
$c = substr($self->{_BUFFER},0,1);
$self->{_BUFFER} = substr($self->{_BUFFER},1);
return $c;
}
READ($self,$c,1) or return undef;
return $c;
}
#------------------------------------------------------------------------------
# CLOSE
#------------------------------------------------------------------------------
sub CLOSE {
my $self = shift;
print "Filesys::SmbClient CLOSE\n" if ($DEBUG);
_close($self->{context}, $self->{FD});
}
#------------------------------------------------------------------------------
# UNTIE
#------------------------------------------------------------------------------
sub UNTIE {
require 5.005_64;
my $self=shift;
print "Filesys::SmbClient UNTIE\n" if ($DEBUG);
CLOSE($self);
undef($self->{_BUFFER});
}
#------------------------------------------------------------------------------
# new
#------------------------------------------------------------------------------
sub new {
my $class = shift;
my $self = {};
my @l;
bless $self, $class;
my %vars;
if (@_) {
%vars =@_;
if (!$vars{'workgroup'}) { $vars{'workgroup'}=""; }
if (!$vars{'username'}) { $vars{'username'}=""; }
if (!$vars{'password'}) { $vars{'password'}=""; }
if (!$vars{'debug'}) { $vars{'debug'}=0; }
push(@l, $vars{'username'});
push(@l, $vars{'password'});
push(@l, $vars{'workgroup'});
push(@l, $vars{'debug'});
print "Filesys::SmbClient new>",join(" ", @l),"\n" if $vars{'debug'};
$self->{params}= \%vars;
}
else { @l =("","","",0); }
$self->{context} = _init(@l);
if ($vars{'useKerberos'}) { _setOptionUseKerberos($self->{context}, $vars{'useKerberos'}); };
if ($vars{'noAutoAnonymousLogin'}) { _setOptionNoAutoAnonymousLogin($self->{context}, $vars{'noAutoAnonymousLogin'}); };
if ($vars{'fallbackAfterKerberos'}) { _setOptionFallbackAfterKerberos($self->{context}, $vars{'fallbackAfterKerberos'}); };
if ($vars{'timeout'} && $vars{'timeout'} =~ /^[0-9]+$/) { _setTimeout($self->{context}, $vars{'timeout'}); };
if ($vars{'port'} && $vars{'port'} =~ /^[0-9]+$/) { _setPort($self->{context}, $vars{'port'}); };
return $self;
}
#------------------------------------------------------------------------------
# readdir_struct
#------------------------------------------------------------------------------
sub readdir_struct {
my $self=shift;
if (wantarray()) {
my @tab;
while (my @l = _readdir($self->{context}, $_[0])) { push(@tab,\@l); }
return @tab;
} else {
my @l = _readdir($self->{context}, $_[0]);
return \@l if (@l);
}
}
#------------------------------------------------------------------------------
# readdir
#------------------------------------------------------------------------------
sub readdir {
my $self=shift;
if (wantarray()) {
my @tab;
while (my @l = _readdir($self->{context}, $_[0])) { push(@tab,$l[1]);}
return @tab;
} else {
my @l =_readdir($self->{context}, $_[0]);
return $l[1];
}
}
#------------------------------------------------------------------------------
# open
#------------------------------------------------------------------------------
sub open {
my ($self,$file,$perms)=@_;
$perms = '0666' if (!$perms);
$self->{_FD} = _open($self->{context}, $file, $perms);
print "Filesys::SmbClient open <$self->{_FD}>\n"
if ($self->{params}->{debug});
return $self->{_FD};
}
#------------------------------------------------------------------------------
# seek
#------------------------------------------------------------------------------
sub seek {
my ($self,$fd,$offset,$whence) = @_;
return -1 if ($fd == -1);
print "Filesys::SmbClient seek\n" if ($self->{params}->{debug});
$whence = SEEK_SET if (!$whence);
warn "Whence diff from SEEK_SET not implemented in smb"
if ($whence ne SEEK_SET);
return _lseek($self->{context}, $fd, $offset, SEEK_SET);
}
#------------------------------------------------------------------------------
# write
#------------------------------------------------------------------------------
sub write {
my $self = shift;
my $fd = shift;
print "Filesys::SmbClient write ".$self.' '.$fd.' '.join(" ",@_)."\n"
if ($self->{params}->{debug});
my $buffer = join("",@_);
return _write($self->{context}, $fd, $buffer, length($buffer));
}
#------------------------------------------------------------------------------
# read
#------------------------------------------------------------------------------
sub read {
my ($self,$fd,$lg)=@_;
$lg = MAX_LENGTH_LINE if (!$lg);
return _read($self->{context}, $fd, $lg);
}
#------------------------------------------------------------------------------
# mkdir
#------------------------------------------------------------------------------
sub mkdir {
my ($self,$dir,$mode)=@_;
$mode = '0755' if (!$mode);
return _mkdir($self->{context}, $dir, $mode);
}
#------------------------------------------------------------------------------
# rmdir_recurse
#------------------------------------------------------------------------------
sub rmdir_recurse {
my $self=shift;
my $url = shift;
my $fd = $self->opendir($url) || return undef;
my @f = $self->readdir_struct($fd);
$self->closedir($fd);
foreach my $v (@f) {
next if ($v->[1] eq '.' or $v->[1] eq '..');
my $u = $url."/".$v->[1];
if ($v->[0] == SMBC_FILE) { $self->unlink($u); }
elsif ($v->[0] == SMBC_DIR) { $self->rmdir_recurse($u); }
}
return $self->rmdir($url);
}
#------------------------------------------------------------------------------
# shutdown
#------------------------------------------------------------------------------
sub shutdown {
my ($self, $flag)=@_;
return _shutdown($self->{context}, $flag);
}
1;
__END__
#------------------------------------------------------------------------------
=pod
=head1 NAME
Filesys::SmbClient - Interface for access Samba filesystem with libsmclient.so
=head1 SYNOPSIS
use POSIX;
use Filesys::SmbClient;
my $smb = new Filesys::SmbClient(username => "alian",
password => "speed",
workgroup => "alian",
debug => 10);
# Read a file
my $fd = $smb->open("smb://jupiter/doc/general.css", '0666');
while (defined(my $l= $smb->read($fd,50))) {print $l; }
$smb->close(fd);
# ...
See section EXAMPLE for others scripts.
=head1 DESCRIPTION
Provide interface to access routine defined in libsmbclient.so provided with
Samba.
Since 3.0 release of this package, you need a least samba-3.0.2.
For prior release of Samba, use Filesys::SmbClient version 1.x.
For old and 2.x release, this library is available on Samba source, but is not
build by default.
Do "make bin/libsmbclient.so" in sources directory of Samba to build
this libraries. Then copy source/include/libsmbclient.h to
/usr/local/samba/include and source/bin/libsmbclient.so to
/usr/local/samba/lib before install this module.
If you want to use filehandle with this module, you need Perl 5.6 or later.
When a path is used, his scheme is :
smb://server/share/rep/doc
=head1 VERSION
$Revision: 3.2 $
=head1 FONCTIONS
=over
=item new %hash
Init connection
Hash can have this keys:
=over
=item *
username
=item *
password
=item *
workgroup
=item *
debug
=back
Return instance of Filesys::SmbClient on succes, die with error else.
Example:
my $smb = new Filesys::SmbClient(username => "alian",
password => "speed",
workgroup => "alian",
debug => 10);
=back
=head2 Tie Filesys::SmbClient filehandle
This didn't work before 5.005_64. Why, I don't know.
When you have tied a filehandle with Filesys::SmbClient,
you can call classic methods for filehandle:
print, printf, seek, syswrite, getc, open, close, read.
See perldoc for usage.
Example:
local *FD;
tie(*FD, 'Filesys::SmbClient');
open(FD,"smb://jupiter/doc/test")
or print "Can't open file:", $!, "\n";
while(<FD>) { print $_; }
close(FD);
or
local *FD;
tie(*FD, 'Filesys::SmbClient');
open(FD,">smb://jupiter/doc/test")
or print "Can't create file:", $!, "\n";
print FD "Samba test","\n";
printf FD "%s", "And that work !\n";
close(FD);
=head2 Directory
=over
=item mkdir FILENAME, MODE
Create directory $fname with permissions set to $mode.
Return 1 on success, else 0 is return and errno and $! is set.
Example:
$smb->mkdir("smb://jupiter/doc/toto",'0666')
or print "Error mkdir: ", $!, "\n";
=item rmdir FILENAME
Erase directory $fname. Return 1 on success, else 0 is return
and errno and $! is set. ($fname must be empty, else see
rmdir_recurse).
Example:
$smb->rmdir("smb://jupiter/doc/toto")
or print "Error rmdir: ", $!, "\n";
=item rmdir_recurse FILENAME
Erase directory $fname. Return 1 on success, else 0 is return
and errno and $! is set. Il $fname is not empty, all files and
dir will be deleted.
Example:
$smb->rmdir_recurse("smb://jupiter/doc/toto")
or print "Error rmdir_recurse: ", $!, "\n";
=item opendir FILENAME
Open directory $fname. Return file descriptor on succes, else 0 is
return and $! is set.
=item readdir FILEHANDLE
Read a directory. In a list context, return the full content of
the directory $fd, else return next element. Each elem is
a name of a directory or files.
Return undef at end of directory.
Example:
my $fd = $smb->opendir("smb://jupiter/doc");
foreach my $n ($smb->readdir($fd)) {print $n,"\n";}
close($fd);
=item readdir_struct FILEHANDLE
Read a directory. In a list context, return the full content of
the directory FILEHANDLE, else return next element. Each element
is a ref to an array with type, name and comment. Type can be :
=over
=item SMBC_WORKGROUP
=item SMBC_SERVER
=item SMBC_FILE_SHARE
=item SMBC_PRINTER_SHARE
=item SMBC_COMMS_SHARE
=item SMBC_IPC_SHARE
=item SMBC_DIR
=item SMBC_FILE
=item SMBC_LINK
=back
Return undef at end of directory.
Example:
my $fd = $smb->opendir("smb://jupiter/doc");
while (my $f = $smb->readdir_struct($fd)) {
if ($f->[0] == SMBC_DIR) {print "Directory ",$f->[1],"\n";}
elsif ($f->[0] == SMBC_FILE) {print "File ",$f->[1],"\n";}
# ...
}
close($fd);
=item closedir FILEHANDLE
Close directory $fd.
=back
=head2 Files
=over
=item stat FILENAME
Stat a file FILENAME. Return a list with info on success,
else an empty list is return and $! is set.
List is made with:
=over
=item *
device
=item *
inode
=item *
protection
=item *
number of hard links
=item *
user ID of owner
=item *
group ID of owner
=item *
device type (if inode device)
=item *
total size, in bytes
=item *
blocksize for filesystem I/O
=item *
number of blocks allocated
=item *
time of last access
=item *
time of last modification
=item *
time of last change
=back
Example:
my @tab = $smb->stat("smb://jupiter/doc/tata");
if ($#tab == 0) { print "Erreur in stat:", $!, "\n"; }
else {
for (10..12) {$tab[$_] = localtime($tab[$_]);}
print join("\n",@tab);
}
=item fstat FILEHANDLE
Like stat, but on a file handle
=item rename OLDNAME,NEWNAME
Changes the name of a file; an existing file NEWNAME will be clobbered.
Returns true for success, false otherwise, with $! set.
Example:
$smb->rename("smb://jupiter/doc/toto","smb://jupiter/doc/tata")
or print "Can't rename file:", $!, "\n";
=item unlink FILENAME
Unlink FILENAME. Return 1 on success, else 0 is return
and errno and $! is set.
Example:
$smb->unlink("smb://jupiter/doc/test")
or print "Can't unlink file:", $!, "\n";
=item open FILENAME
=item open FILENAME, MODE
Open file $fname with perm $mode. Return file descriptor
on success, else 0 is return and $! is set.
Example:
my $fd = $smb->open("smb://jupiter/doc/test", 0666)
or print "Can't read file:", $!, "\n";
my $fd = $smb->open(">smb://jupiter/doc/test", 0666)
or print "Can't create file:", $!, "\n";
my $fd = $smb->open(">>smb://jupiter/doc/test", 0666)
or print "Can't append to file:", $!, "\n";
=item read FILEHANDLE
=item read FILEHANDLE, LENGTH
Read $count bytes of data on file descriptor $fd. It lenght is not set,
4096 bytes will be read.
Return buffer read on success, undef at end of file,
-1 is return on error and $! is set.
FILEHANDLE must be open with open of this module.
=item write FILEHANDLE, $buf
=item write FILEHANDLE, @buf
Write $buf or @buf on file descriptor $fd.
Return number of bytes wrote, else -1 is return and errno and $! is set.
Example:
my $fd = $smb->open(">smb://jupiter/doc/test", 0666)
or print "Can't create file:", $!, "\n";
$smb->write($fd, "A test of write call")
or print $!,"\n";
$smb->close($fd);
FILEHANDLE must be open with open of this module.
=item seek FILEHANDLE, POS
Sets FILEHANDLE's position, just like the "fseek"
call of "stdio". FILEHANDLE may be an expression
whose value gives the name of the filehandle. The
values for WHENCE is always SEEK_SET beacause others
didn't work on libsmbclient.so
FILEHANDLE must be open with open of this module.
=item close FILEHANDLE
Close file FILEHANDLE. Return 0 on success, else -1 is return and
errno and $! is set.
=back
=item shutdown flag
A wrapper around `libsmbclient's `smbc_free_context'.
Close open files, release Samba connection, delete context,
aquired during open_* calls.
Example:
$smb->shutdown(0); # Gracefully close connection
$sbm->shutdown(1); # Forcibly close files and connection
NOTE:
shutdown(1) may cause complaints about talloc memory
leaks, if there are currently no open files.
=head2 Print method
=over
=item unlink_print_job PRINTER_URL, IDJOB
Remove job number IDJOB on printer PRINTER_URL
=item print_file DOCUMENT_URL, PRINTER_URL
Print file DOCUMENT_URL on PRINTER_URL
=back
=head1 TODO
=over
=item *
chown
=item *
chmod
=item *
open_print_job
=item *
telldir
=item *
lseekdir
=back
=head1 EXAMPLE
This module come with some scripts:
=over
=item t/*.t
Just for check that this module is ok :-)
=item smb2www-2.cgi
A CGI interface with these features:
=over
=item *
browse workgroup ,share, dir
=item *
read file
=item *
upload file
=item *
create directory
=item *
unlink file, directory
=back
=back
=head1 COPYRIGHT
The Filesys-SmbClient module is Copyright (c) 1999-2003 Alain BARBET, France,
alian at cpan.org. All rights reserved.
You may distribute under the terms of either the GNU General
Public License or the Artistic License, as specified
in the Perl README file.
=cut

View File

@ -0,0 +1,516 @@
#include "config.h"
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <samba-4.0/libsmbclient.h>
#include "libauthSamba.h"
#include "config.h"
/*
* Ce fichier definit les fonctions d'interface avec libsmbclient.so
*/
MODULE = Filesys::SmbClient PACKAGE = Filesys::SmbClient
PROTOTYPES: ENABLE
SMBCCTX *
_init(user, password, workgroup, debug)
char *user
char *password
char* workgroup
int debug
CODE:
/*
* Initialize things ...
*/
SMBCCTX *context;
context = smbc_new_context();
if (!context) {
XSRETURN_UNDEF;
}
smbc_setDebug(context, 4); //4 gives a good level of trace.
set_fn(workgroup, user, password);
smbc_setFunctionAuthData(context, auth_fn);
smbc_setDebug(context, debug);
if (smbc_init_context(context) == 0) {
smbc_free_context(context, 1);
XSRETURN_UNDEF;
}
RETVAL = context;
#ifdef VERBOSE
fprintf(stderr, "! Filesys::SmbClient : "
"init %p context\n", context);
#endif
OUTPUT:
RETVAL
int
_shutdown(SMBCCTX *context, int flag)
CODE:
smbc_free_context(context, flag);
RETVAL = 1;
OUTPUT:
RETVAL
NO_OUTPUT void
_setOptionUseKerberos(SMBCCTX *context, int b)
CODE:
smbc_setOptionUseKerberos(context, b);
NO_OUTPUT void
_setOptionNoAutoAnonymousLogin(SMBCCTX *context, int b)
CODE:
smbc_setOptionNoAutoAnonymousLogin(context, b);
NO_OUTPUT void
_setOptionFallbackAfterKerberos(SMBCCTX *context, int b)
CODE:
smbc_setOptionFallbackAfterKerberos(context, b);
NO_OUTPUT void
_setTimeout(SMBCCTX *context, int timeout)
CODE:
smbc_setTimeout(context, timeout);
NO_OUTPUT void
_setPort(SMBCCTX *context, int port)
CODE:
smbc_setPort(context, port);
int
_mkdir(SMBCCTX *context, char *fname, int mode)
CODE:
/*
* Create directory fname
*
*/
RETVAL = smbc_getFunctionMkdir(context)(context, fname, mode);
if (RETVAL < 0) {
RETVAL=0;
#ifdef VERBOSE
fprintf(stderr, "*** Error Filesys::SmbClient : "
"mkdir %s directory : %s\n", fname,strerror(errno));
#endif
}
else RETVAL = 1;
OUTPUT:
RETVAL
int
_rmdir(context, fname)
SMBCCTX *context
char *fname
CODE:
/*
* Remove directory fname
*
*/
RETVAL = smbc_getFunctionRmdir(context)(context, fname);
if (RETVAL < 0) {
RETVAL = 0;
#ifdef VERBOSE
fprintf(stderr, "*** Error Filesys::SmbClient : "
"rmdir %s directory : %s\n", fname,strerror(errno));
#endif
} else RETVAL = 1;
OUTPUT:
RETVAL
SMBCFILE *
_opendir(context, fname)
SMBCCTX *context
char *fname
CODE:
/*
* Open directory fname
*
*/
RETVAL = smbc_getFunctionOpendir(context)(context, fname);
#ifdef VERBOSE
fprintf(stderr, "! Filesys::SmbClient : _opendir: %d\n", RETVAL);
#endif
if (RETVAL < 0) {
RETVAL = 0;
#ifdef VERBOSE
fprintf(stderr, "*** Error Filesys::SmbClient : "
"Error opendir %s : %s\n", fname, strerror(errno));
#endif
}
OUTPUT:
RETVAL
int
_closedir(context, fd)
SMBCCTX *context
SMBCFILE *fd
CODE:
/*
* Close file descriptor for directory fd
*
*/
RETVAL = smbc_getFunctionClosedir(context)(context, fd);
#ifdef VERBOSE
if (RETVAL < 0) {
fprintf(stderr, "*** Error Filesys::SmbClient : "
"Closedir : %s\n", strerror(errno)); }
#endif
OUTPUT:
RETVAL
void
_readdir(context, fd)
SMBCCTX *context
SMBCFILE *fd
PREINIT:
/*
* Read file descriptor for directory fd and return file type, name and comment
*
*/
struct smbc_dirent * dirp;
PPCODE:
#ifdef VERBOSE
fprintf(stderr, "! Filesys::SmbClient : _readdir: %d\n", fd);
#endif
// Fix for rt#12221 : macro "readdir" passed 2 arguments, but takes just 1
// Seems only work on linux, not solaris
// Already defined in usr/lib/perl/5.8/CORE/reentr.inc:1322:# define readdir(a)
#if !(defined (__SVR4) && defined (__sun)) && !defined(_AIX)
#undef readdir
#endif
dirp = (struct smbc_dirent *)smbc_getFunctionReaddir(context)(context, fd);
if (dirp) {
XPUSHs(sv_2mortal(newSVnv(dirp->smbc_type)));
/*
* original code here produces strings which include NULL as last char
* with samba 3. Reported by dpavlin at rot13.org
*
XPUSHs(sv_2mortal((SV*)newSVpv(dirp->name, dirp->namelen)));
XPUSHs(sv_2mortal((SV*)newSVpv(dirp->comment, dirp->commentlen)));
*/
XPUSHs(sv_2mortal((SV*)newSVpv(dirp->name, strlen(dirp->name))));
XPUSHs(sv_2mortal((SV*)newSVpv(dirp->comment, strlen(dirp->comment))));
}
void
_stat(context, fname)
SMBCCTX *context
char *fname
PREINIT:
/*
* _stat(fname) : Get information about a file or directory.
*
*/
int i;
struct stat buf;
PPCODE:
i = smbc_getFunctionStat(context)(context, fname, &buf);
if (i == 0) {
XPUSHs(sv_2mortal(newSVnv(buf.st_dev)));
XPUSHs(sv_2mortal(newSVnv(buf.st_ino)));
XPUSHs(sv_2mortal(newSVnv(buf.st_mode)));
XPUSHs(sv_2mortal(newSVnv(buf.st_nlink)));
XPUSHs(sv_2mortal(newSVnv(buf.st_uid)));
XPUSHs(sv_2mortal(newSVnv(buf.st_gid)));
XPUSHs(sv_2mortal(newSVnv(buf.st_rdev)));
XPUSHs(sv_2mortal(newSVnv(buf.st_size)));
XPUSHs(sv_2mortal(newSVnv(buf.st_blksize)));
XPUSHs(sv_2mortal(newSVnv(buf.st_blocks)));
XPUSHs(sv_2mortal(newSVnv(buf.st_atime)));
XPUSHs(sv_2mortal(newSVnv(buf.st_mtime)));
XPUSHs(sv_2mortal(newSVnv(buf.st_ctime)));
} else {
#ifdef VERBOSE
fprintf(stderr, "! Filesys::SmbClient : Stat: %s\n", strerror(errno));
#endif
XPUSHs(sv_2mortal(newSVnv(0)));
}
void
_fstat(context, fd)
SMBCCTX *context
SMBCFILE *fd
PREINIT:
/*
* Get information about a file or directory via a file descriptor.
*
*/
int i;
struct stat buf;
PPCODE:
i = smbc_getFunctionFstat(context)(context, fd, &buf);
if (i == 0) {
XPUSHs(sv_2mortal(newSVnv(buf.st_dev)));
XPUSHs(sv_2mortal(newSVnv(buf.st_ino)));
XPUSHs(sv_2mortal(newSVnv(buf.st_mode)));
XPUSHs(sv_2mortal(newSVnv(buf.st_nlink)));
XPUSHs(sv_2mortal(newSVnv(buf.st_uid)));
XPUSHs(sv_2mortal(newSVnv(buf.st_gid)));
XPUSHs(sv_2mortal(newSVnv(buf.st_rdev)));
XPUSHs(sv_2mortal(newSVnv(buf.st_size)));
XPUSHs(sv_2mortal(newSVnv(buf.st_blksize)));
XPUSHs(sv_2mortal(newSVnv(buf.st_blocks)));
XPUSHs(sv_2mortal(newSVnv(buf.st_atime)));
XPUSHs(sv_2mortal(newSVnv(buf.st_mtime)));
XPUSHs(sv_2mortal(newSVnv(buf.st_ctime)));
} else {
XPUSHs(sv_2mortal(newSVnv(errno)));
}
int
_rename(context, oname, nname)
SMBCCTX *context
char *oname
char *nname
CODE:
/*
* Rename old file oname in nname
*
*/
RETVAL = smbc_getFunctionRename(context)(context, oname, context, nname);
if (RETVAL < 0) {
RETVAL = 0;
#ifdef VERBOSE
fprintf(stderr, "*** Error Filesys::SmbClient : "
"Rename %s in %s : %s\n", oname, nname, strerror(errno));
#endif
} else {
RETVAL = 1;
}
OUTPUT:
RETVAL
SMBCFILE*
_open(context, fname, mode)
SMBCCTX *context
char *fname
int mode
PREINIT:
/*
* Open file fname with perm mode
*
*/
int flags;
int seek_end = 0;
CODE:
/* Mode >> */
if ( (*fname != '\0') && (*(fname+1) != '\0') &&
(*fname == '>') && (*(fname+1) == '>')) {
flags = O_WRONLY | O_CREAT | O_APPEND;
fname+=2;
seek_end = 1;
#ifdef VERBOSE
fprintf(stderr, "! Filesys::SmbClient :"
"Open append %s : %s\n", fname);
#endif
/* Mode > */
} else if ( (*fname != '\0') && (*fname == '>')) {
flags = O_WRONLY | O_CREAT | O_TRUNC; fname++;
/* Mode < */
} else if ( (*fname != '\0') && (*fname == '<')) {
flags = O_RDONLY; fname++;
/* Mod < */
} else flags = O_RDONLY;
RETVAL = smbc_getFunctionOpen(context)(context, fname, flags, mode);
#ifdef VERBOSE
fprintf(stderr, "! Filesys::SmbClient :"
"Open %s return %d\n", fname, RETVAL);
#endif
if (RETVAL < 0) {
RETVAL = 0;
#ifdef VERBOSE
fprintf(stderr, "*** Error Filesys::SmbClient :"
"Open %s : %s\n", fname, strerror(errno));
#endif
} else if (seek_end) { smbc_getFunctionLseek(context)(context, RETVAL, 0, SEEK_END); }
OUTPUT:
RETVAL
SV*
_read(context,fd, count)
SMBCCTX *context
SMBCFILE *fd
int count
PREINIT:
/*
* Read count bytes on file descriptor fd
*
*/
char *buf;
int returnValue;
CODE:
buf = (char*)alloca(sizeof(char)*(count+1));
returnValue = smbc_getFunctionRead(context)(context, fd, buf, count);
buf[returnValue]='\0';
#ifdef VERBOSE
if (returnValue <= 0){
fprintf(stderr, "*** Error Filesys::SmbClient: "
"Read %s : %s\n", buf, strerror(errno));
}
#endif
if (returnValue<0) {RETVAL=&PL_sv_undef;}
else {RETVAL=newSVpvn(buf,returnValue);}
OUTPUT:
RETVAL
int
_write(context, fd, buf, count)
SMBCCTX *context
SMBCFILE *fd
char *buf
int count
CODE:
/*
* Write buf on file descriptor fd
*
*/
RETVAL=smbc_getFunctionWrite(context)(context, fd, buf, count);
#ifdef VERBOSE
fprintf(stderr, "! Filesys::SmbClient :"
"write %d bytes: %s\n",count, buf);
if (RETVAL < 0) {
if (RETVAL == EBADF)
fprintf(stderr, "*** Error Filesys::SmbClient: "
"write fd non valide\n");
else if (RETVAL == EINVAL)
fprintf(stderr, "*** Error Filesys::SmbClient: "
"write param non valide\n");
else
fprintf(stderr, "*** Error Filesys::SmbClient: "
"write %d : %s\n", fd, strerror(errno));
}
#endif
OUTPUT:
RETVAL
int
_lseek(context, fd,offset,whence)
SMBCCTX *context
SMBCFILE *fd
int offset
int whence
CODE:
RETVAL=smbc_getFunctionLseek(context)(context, fd, offset, whence);
#ifdef VERBOSE
if (RETVAL < 0) {
if (RETVAL == EBADF)
fprintf(stderr, "*** Error Filesys::SmbClient: "
"lseek fd not open\n");
else if (RETVAL == EINVAL)
fprintf(stderr, "*** Error Filesys::SmbClient: "
"smbc_init not called or fd not a filehandle\n");
else
fprintf(stderr, "*** Error Filesys::SmbClient: "
"write %d : %s\n", fd, strerror(errno));
}
#endif
OUTPUT:
RETVAL
int
_close(context, fd)
SMBCCTX *context
SMBCFILE *fd
CODE:
/*
* Close file desriptor fd
*
*/
RETVAL=smbc_getFunctionClose(context)(context, fd);
OUTPUT:
RETVAL
int
_unlink(context, fname)
SMBCCTX *context
char *fname
CODE:
/*
* Remove file fname
*
*/
RETVAL = smbc_getFunctionUnlink(context)(context, fname);
if (RETVAL < 0) {
RETVAL = 0;
#ifdef VERBOSE
fprintf(stderr, "*** Error Filesys::SmbClient: Failed to unlink %s : %s\n",
fname, strerror(errno));
#endif
} else RETVAL = 1;
OUTPUT:
RETVAL
int
_unlink_print_job(purl, id)
char *purl
int id
CODE:
/*
* Remove job print no id on printer purl
*
*/
RETVAL = smbc_unlink_print_job(purl, id);
#ifdef VERBOSE
if (RETVAL<0)
fprintf(stderr, "*** Error Filesys::SmbClient: "
"Failed to unlink job id %u on %s, %s, %u\n",
id, purl, strerror(errno), errno);
#endif
OUTPUT:
RETVAL
int
_print_file(purl, printer)
char *purl
char *printer
CODE:
/*
* Print url purl on printer purl
*
*/
RETVAL = smbc_print_file(purl, printer);
#ifdef VERBOSE
if (RETVAL<0)
fprintf(stderr, "*** Error Filesys::SmbClient *** "
"Failed to print file %s on %s, %s, %u\n",
purl, printer, strerror(errno), errno);
#endif
OUTPUT:
RETVAL

View File

@ -0,0 +1,64 @@
#include <stdio.h>
#include <string.h>
#include "libauthSamba.h"
char User[100];
char Password[100];
char Workgroup[100];
/*-----------------------------------------------------------------------------
* set_fn
*---------------------------------------------------------------------------*/
void set_fn(char *workgroup,
char *username,
char *password)
{
#ifdef VERBOSE
printf("set_fn\n");
#endif
strcpy(User, username);
strcpy(Password, password);
/* set workgroup only when set */
if (workgroup[0] && workgroup[0] != 0) {
#ifdef VERBOSE
fprintf("Workgroup is set to %s", workgroup);
#endif
strcpy(Workgroup, workgroup);
}
}
/*-----------------------------------------------------------------------------
* auth_fn
*---------------------------------------------------------------------------*/
void auth_fn(const char *server,
const char *share,
char *workgroup, int wgmaxlen,
char *username, int unmaxlen,
char *password, int pwmaxlen) {
#ifdef VERBOSE
printf("auth_fn\n");
#endif
/* set workgroup only when set */
if (Workgroup[0] && Workgroup[0] != 0) {
#ifdef VERBOSE
fprintf("Workgroup is set to %s", Workgroup);
#endif
strcpy(workgroup, Workgroup);
wgmaxlen = 100;
}
strcpy(username, User);
unmaxlen = 100;
strcpy(password, Password);
pwmaxlen = 100;
#ifdef VERBOSE
fprintf(stdout, "username: [%s]\n", username);
fprintf(stdout, "password: [%s]\n", password);
fprintf(stdout, "workgroup: [%s]\n", workgroup);
#endif
}

View File

@ -0,0 +1,9 @@
void set_fn( char *workgroup,
char *username,
char *password);
void auth_fn(const char *server,
const char *share,
char *workgroup, int wgmaxlen,
char *username, int umaxlen,
char *password, int pwmaxlen);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
#!/usr/bin/perl -w
use Test::More;
use Filesys::SmbClient;
use strict;
use diagnostics;
plan tests=>19;
my $loaded = 1;
ok($loaded,"Load module");
my $buffer = "A test of write call\n";
my $buffer2 = "buffer of 1234\n";
SKIP: {
skip "No server defined for test at perl Makefile.PL", 18 if (!-e ".c");
if (-e ".c") {
use POSIX;
my $ok = 0;
open(F,".c") || die "Can't read .c\n";
my $l = <F>; chomp($l);
my @l = split(/\t/, $l);
my %param =
(
username => $l[3],
password => $l[4],
workgroup => $l[2],
debug => 0,
# flags => SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON
);
my $smb = new Filesys::SmbClient(%param);
my $server = "smb://$l[0]/$l[1]";
# Create a directory
ok($smb->mkdir("$server/toto",'0666'),"Create directory")
or diag("With $!");
# Create a existent directory
ok(!$smb->mkdir("$server/toto",'0666'),"Create existent directory");
# Write a file
my $fd = $smb->open(">$server/toto/test",0666);
if ($fd) {
$ok = 1 if ($smb->write($fd,$buffer));
}
$smb->close($fd);
ok($ok,"Create file");
$ok=0;
# Rename a file
ok($smb->rename("$server/toto/test","$server/toto/tata"),"Rename file")
or diag("With $!");
# Stat a file
my @tab = $smb->stat("$server/toto/tata");
ok($#tab != 0,"Stat file ") or diag("With $!");
# Stat a non-existent file
@tab = $smb->stat("smb://jupidsdsdster/soft/lala");
ok($#tab == 0,"Stat non-existent file") or diag("With $!");
# Read a file
my $buf;
$fd = $smb->open("$server/toto/tata",'0666');
while (my $l= $smb->read($fd,50)) {$buf.=$l; }
if (!$buf) { ok(0, "Read file"); }
else {
ok(length($buf) == length($buffer),"Read file")
or diag("read ",length($buf)," bytes)");
}
$smb->close($fd);
# Directory
# Read a directory
$fd = $smb->opendir("$server/toto");
my @a;
if ($fd) {
foreach my $n ($smb->readdir($fd)) {push(@a,$n);}
$ok = 1 if ($#a==2);
$smb->close($fd);
}
ok($ok,"Read short directory"); $ok=0;
# Read long info on a directory
undef @a;
$fd = $smb->opendir("$server/toto");
if ($fd) {
while (my $f = $smb->readdir_struct($fd)) { push(@a,$f); }
$ok = 1 if ($#a==2);
$smb->close($fd);
}
ok($ok,"Read long directory");
# Unlink a file
ok($smb->unlink("$server/toto/tata"),"Unlink file")
or diag("With $!");
# Unlink a non-existent file
ok(!$smb->unlink("$server/toto/tatarr"),"Unlink non-existent file");
ok($smb->mkdir("$server/toto/tate",'0666'),"Create directory")
or diag("With $!");
ok($smb->mkdir("$server/toto/tate/titi",'0666'),"Create directory")
or diag("With $!");
ok($smb->rmdir_recurse("$server/toto/tate",'0666'),
"Rmdir entire directory") or diag("With $!");
# Erase this directory
ok($smb->rmdir("$server/toto/"),"Rm directory") or diag("With $!");
# Erase non-existent directory
ok(!$smb->rmdir("$server/totoarr/"),"Rm non-existent directory");
# Rename a non-existent file
ok(!$smb->rename("$server/toto/testrr","$server/toto/tata"),
"Rename non-existent file");
print "There is a .c file in this directory with info about your params \n",
"for you SMB server test. Think to remove it if you have finish \n",
"with test.\n\n";
ok( $smb->shutdown(0), "shutdown");
}
}

View File

@ -0,0 +1,140 @@
#!/usr/bin/perl -w
use Test::More;
use Filesys::SmbClient;
use strict;
#use diagnostics;
use File::Copy;
use POSIX;
use Config;
if( !$Config{'PERL_API_REVISION'} or !$Config{'PERL_VERSION'} or
($Config{'PERL_API_REVISION'} != 5 or $Config{PERL_VERSION}<6)) {
plan skip_all =>
'tie filehandle for Filesys::SmbClient didn\'t work before Perl 5.6';
}
else {
plan tests => 25;
}
require Filesys::SmbClient;
my $buffer = "A test of write call\n";
my $buffer2 = "buffer of 1234\n";
SKIP: {
skip "No server defined for test at perl Makefile.PL", 25 if (!-e ".c");
my $ok = 0;
my (%param,$server);
if (open(F,".c")) {
my $l = <F>; chomp($l);
my @l = split(/\t/, $l);
%param =
(
username => $l[3],
password => $l[4],
workgroup => $l[2],
debug => 0
);
$server = "smb://$l[0]/$l[1]";
}
my $smb = new Filesys::SmbClient(%param);
# Create a directory
ok($smb->mkdir("$server/toto"),"Create directory")
or diag("With $!");
# Create a file with open / tie
local *FD;
tie(*FD, 'Filesys::SmbClient',">$server/toto/tata", 0755, %param);
ok(fileno(FD), "tie & open");
# PRINT
print FD $buffer;
# PRINTF
printf FD "%s",$buffer2;
# PRINT IN LIST CONTEXT
print FD "6","\n";
# SYSWRITE
my $lg = syswrite(FD,"6\n");
is($lg,2,"TIE: return of syswrite");
close(FD);
$lg = syswrite(FD,"6\n");
is($lg,undef,"TIE: return of syswrite on a closed filehandle");
untie(*FD);
# Read a file with open/tie
my $f;
tie(*FD,'Filesys::SmbClient',"$server/toto/tata", 0755, %param);
# TIEHANDLE
ok(fileno(FD),"TIE: tie & open a file") or diag("With $!");
# try to copy file with File::Copy
copy(\*FD, "/tmp/toto");
ok(-e "/tmp/toto", "copy a filehandle with File::Copy");
# SEEK
seek(FD,0,SEEK_SET);
# READLINE
is(scalar<FD>,$buffer, "TIE: Read one ligne of a file");
is(scalar<FD>,$buffer2, "TIE: Read another ligne of a file");
# GETC
is(getc(FD),6,"TIE: getc of a file");
is(getc(FD),"\n","TIE: getc of a file");
is(getc(FD),6,"TIE: getc of a file");
is(getc(FD),"\n","TIE: getc of a file");
# SEEK
my $rr = seek(FD,0,SEEK_SET);
is(getc(FD),"A","TIE: seek SEEK_SET a file");
undef $rr;
# READ
$lg = read(FD,$rr,4);
is($lg, 4,"TIE: Return of read");
is($rr, " tes", "TIE: buffer read");
# SEEK_CUR
$rr = seek(FD,2,SEEK_CUR);
is(getc(FD),"o","TIE: Seek SEEK_CUR a file open");
# SEEK_END
$rr = seek(FD,0,SEEK_END);
is(getc(FD), undef, "TIE: Seek SEEK_END a file open");
# sysread at end of file
$lg = sysread(FD, $rr, 5);
is($lg, 0, "TIE: sysread return 0 at end of file");
close(FD);
# seek closed file
is(seek(FD,0,SEEK_SET),-1,"TIE: seek return undef on closed file");
# read closed file
is(read(FD,$rr,4), undef, "TIE: read return undef on closed file");
# sysread closed file
is(sysread(FD,$rr,4), undef, "TIE: sysread return undef on closed file");
# Read a file with opentie in list context
undef $f;
open(FD,"$server/toto/tata");
my @l2 = <FD>;
close(FD);
is(join('',@l2),$buffer.$buffer2."6\n"x2,
"TIE: Read a file in list context");
# Unlink a file
ok($smb->unlink("$server/toto/tata"),"Unlink file")
or diag("With $!");
untie(*FD);
# Opentie a non existant file
tie(*FD,'Filesys::SmbClient',"$server/toto/tataa", 0755, %param);
ok(!fileno(FD), "TIE: open a non-existent file");
# Erase this directory
ok($smb->rmdir("$server/toto/"),"Rm directory") or diag("With $!");
}

View File

@ -0,0 +1,110 @@
#!/usr/bin/perl -w
use Test::More;
use Filesys::SmbClient;
use strict;
use diagnostics;
use Config;
if( !$Config{'PERL_API_REVISION'} or !$Config{'PERL_VERSION'} or
($Config{'PERL_API_REVISION'} != 5 or $Config{PERL_VERSION}<6)) {
plan skip_all =>
'tie filehandle for Filesys::SmbClient didn\'t work before Perl 5.6';
}
else {
plan tests => 20;
}
require Filesys::SmbClient;
my $buffer = "A test of write call\n";
my $buffer2 = "buffer of 1234\n";
SKIP: {
skip "No server defined for test at perl Makefile.PL", 20 if (!-e ".c");
if (-e ".c") {
use POSIX;
my $ok = 0;
open(F,".c") || die "Can't read .c\n";
my $l = <F>; chomp($l);
my @l = split(/\t/, $l);
my %param =
(
username => $l[3],
password => $l[4],
workgroup => $l[2],
debug => 0
);
my $smb = new Filesys::SmbClient(%param);
my $server = "smb://$l[0]/$l[1]";
# Create a directory
ok($smb->mkdir("$server/toto"),"Create directory")
or diag("With $!");
# Create a file with open / tie
local *FD;
tie(*FD, 'Filesys::SmbClient', undef, undef, %param);
ok(open(FD, ">$server/toto/tata"),
"TIE: open to create a file")
or diag("With $!");
# PRINT
print FD $buffer;
# PRINTF
printf FD "%s",$buffer2;
# PRINT IN LIST CONTEXT
print FD "6","\n";
# SYSWRITE
my $lg = syswrite(FD,"6\n");
is($lg,2,"TIE: return of syswrite");
close(FD);
$lg = syswrite(FD,"6\n");
is($lg,undef,"TIE: return of syswrite on a closed filehandle");
# Read a file with open/tie
my $f;
# TIEHANDLE
ok(open(FD,"$server/toto/tata"),"TIE: read a file") or diag("With $!");
# READLINE
is(scalar<FD>,$buffer, "TIE: Read one ligne of a file");
is(scalar<FD>,$buffer2, "TIE: Read another ligne of a file");
# GETC
is(getc(FD),6,"TIE: getc of a file");
is(getc(FD),"\n","TIE: getc of a file");
is(getc(FD),6,"TIE: getc of a file");
is(getc(FD),"\n","TIE: getc of a file");
# SEEK
my $rr = seek(FD,0,SEEK_SET);
is(getc(FD),"A","TIE: seek SEEK_SET a file");
undef $rr;
# READ
$lg = read(FD,$rr,4);
is($lg, 4,"TIE: Return of read");
is($rr, " tes", "TIE: buffer read");
# $rr = seek(FD,2,SEEK_CUR);
# is(getc(FD),"f","Seek SEEK_CUR a file open with opentie");
# $rr = seek(FD,0,SEEK_END);
# is(getc(FD),"b","Seek SEEK_END a file open with opentie");
close(FD);
is(seek(FD,0,SEEK_SET),-1,"TIE: seek closed file");
is(read(FD,$rr,4), undef, "TIE: read closed file");
# Read a file with opentie in list context
undef $f;
open(FD,"$server/toto/tata");
my @l2 = <FD>;
close(FD);
is(join('',@l2),$buffer.$buffer2."6\n"x2,
"TIE: Read a file in list context");
# Unlink a file
ok($smb->unlink("$server/toto/tata"),"Unlink file")
or diag("With $!");
# Opentie a non existant file
ok(!open(FD,"$server/toto/tataa"), "TIE: open a non-existent file");
# Erase this directory
ok($smb->rmdir("$server/toto/"),"Rm directory") or diag("With $!");
}
}

View File

@ -0,0 +1,4 @@
const char * T_Pv
struct smbc_dirent * T_PTROBJ
SMBCCTX * T_PTROBJ
SMBCFILE * T_PTROBJ

View File

@ -0,0 +1,63 @@
name: "@NAME@"
arch: "${ARCH}"
platform: "linux"
version_schema: "none"
version: "@VERSION@"
release: "2${DIST}"
section: "default"
priority: "optional"
maintainer: "Centreon <contact@centreon.com>"
description: |
This module implements JSONPath, an XPath-like language for searching JSON-like structures.
JSONPath is described at http://goessner.net/articles/JsonPath/.
Commit: @COMMIT_HASH@
vendor: "Centreon"
homepage: "https://www.centreon.com"
license: "Apache-2.0"
contents:
- src: "/tmp/lib/perl5/JSON/Path.pm"
dst: "@PERL_VENDORLIB@/JSON/"
file_info:
mode: 0644
- src: "/tmp/lib/perl5/JSON/Path/"
dst: "@PERL_VENDORLIB@/JSON/Path/"
file_info:
mode: 0644
- src: "/tmp/man/man3/JSON::Path*"
dst: "/usr/share/man/man3/"
file_info:
mode: 0644
overrides:
rpm:
depends:
- perl(Carp::Assert)
- perl(Exporter::Tiny)
- perl(JSON::MaybeXS)
- perl(JSON::Parse)
- perl(LV)
- perl(List::Util)
- perl(Readonly)
- perl(Tie::IxHash)
- perl(Try::Tiny)
provides:
- perl(JSON::Path)
deb:
depends:
- libcarp-assert-perl
- libexporter-tiny-perl
- libjson-parse-perl
- liblv-perl
- libreadonly-perl
- libtie-ixhash-perl
- libtry-tiny-perl
rpm:
summary: This module implements JSONPath, an XPath-like language for searching JSON-like structures
compression: zstd
signature:
key_file: ${RPM_SIGNING_KEY_FILE}
key_id: ${RPM_SIGNING_KEY_ID}

View File

@ -0,0 +1,48 @@
Name: perl-KeePass-Reader
Version: 0.2
Release: 2%{?dist}
Summary: Interface to KeePass V4 database files
Group: Development/Libraries
License: Apache2
URL: https://github.com/garnier-quentin/perl-KeePass-Reader
Source0: %{name}.tar.gz
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: make
BuildRequires: perl(ExtUtils::MakeMaker)
Requires: perl(Crypt::Argon2)
%description
KeePass::Reader is a perl interface to read KeePass version 4.
%prep
%setup -q -n %{name}
%build
%{__perl} Makefile.PL INSTALLDIRS=vendor OPTIMIZE="$RPM_OPT_FLAGS"
make %{?_smp_mflags}
%install
rm -rf %{buildroot}
make pure_install PERL_INSTALL_ROOT=$RPM_BUILD_ROOT
find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type f -name '*.bs' -a -size 0 -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type d -depth -exec rmdir {} 2>/dev/null ';'
rm -rf $RPM_BUILD_ROOT%{_usr}/bin/hexdump
%{_fixperms} $RPM_BUILD_ROOT/*
%check
#make test
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{perl_vendorlib}
%{_mandir}/man3/*.3*
%changelog

View File

@ -0,0 +1,24 @@
# git
\B\.git\b
\B\.gitignore\b
# build files
^blib
^_build
^Build$
^cover_db
^Makefile(\.old)?$
^MANIFEST\.
^pm_to_blib$
# contrib
^contrib
^files
# packages
^packaging
# temporary
~$
\.bak$
\.old$

View File

@ -0,0 +1,13 @@
use 5.008005;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'KeePass::Reader',
VERSION_FROM => 'lib/KeePass/Reader.pm',
PREREQ_PM => { 'Test::More' => 0 },
ABSTRACT_FROM => 'lib/KeePass/Reader.pm',
AUTHOR => 'Quentin Garnier',
LIBS => [],
DEFINE => '',
INC => '',
OBJECT => ''
);

View File

@ -0,0 +1,53 @@
package KeePass::Crypto::Aes2Kdf;
use strict;
use warnings;
use POSIX;
use KeePass::constants qw(:all);
use Crypt::Mode::ECB;
use Crypt::Digest::SHA256;
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
return $self;
}
sub seed {
my ($self, %options) = @_;
return $self->{m_seed};
}
sub process_parameters {
my ($self, %options) = @_;
$self->{m_seed} = $options{params}->{&KdfParam_Aes_Seed};
if (!defined($self->{m_seed}) || length($self->{m_seed}) < Kdf_Min_Seed_Size || length($self->{m_seed}) > Kdf_Max_Seed_Size) {
return 1;
}
$self->{m_rounds} = $options{params}->{&KdfParam_Aes_Rounds};
if (!defined($self->{m_rounds}) || $self->{m_rounds} < 1 || $self->{m_rounds} > POSIX::INT_MAX) {
return 1;
}
return 0;
}
sub transform {
my ($self, %options) = @_;
# Should use Argon2
my $cbc = Crypt::Mode::ECB->new('AES');
my $transform_key = $options{raw_key};
for (my $i = 0; $i < $self->{m_rounds}; $i++) {
$transform_key = $cbc->encrypt($transform_key, $self->{m_seed});
}
return Crypt::Digest::SHA256::sha256($transform_key);
}
1;

View File

@ -0,0 +1,92 @@
package KeePass::Crypto::Argon2Kdf;
use strict;
use warnings;
use POSIX;
use KeePass::constants qw(:all);
use Crypt::Argon2;
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
$self->{type} = KeePass2_Kdf_Argon2Id;
if ($options{type} eq KeePass2_Kdf_Argon2D) {
$self->{type} = KeePass2_Kdf_Argon2D;
}
$self->{m_version} = 0x13;
$self->{m_memory} = 1 << 16;
$self->{m_parallelism} = 4;
$self->{m_rounds} = 10;
return $self;
}
sub seed {
my ($self, %options) = @_;
return $self->{m_seed};
}
sub process_parameters {
my ($self, %options) = @_;
$self->{m_seed} = $options{params}->{&KdfParam_Argon2_Salt};
if (!defined($self->{m_seed}) || length($self->{m_seed}) < Kdf_Min_Seed_Size || length($self->{m_seed}) > Kdf_Max_Seed_Size) {
return 1;
}
$self->{m_version} = $options{params}->{&KdfParam_Argon2_Version};
if (!defined($self->{m_version}) || $self->{m_version} < 0x10 || $self->{m_version} > 0x13) {
return 1;
}
$self->{m_parallelism} = $options{params}->{&KdfParam_Argon2_Parallelism};
if (!defined($self->{m_parallelism}) || $self->{m_parallelism} < 1 || $self->{m_parallelism} > (1 << 24)) {
return 1;
}
$self->{m_memory} = $options{params}->{&KdfParam_Argon2_Memory};
return 1 if (!defined($self->{m_memory}));
$self->{m_memory} /= 1024; # KB
if ($self->{m_memory} < 8 || $self->{m_memory} > (1 << 32)) {
return 1;
}
$self->{m_rounds} = $options{params}->{&KdfParam_Argon2_Iterations};
if (!defined($self->{m_rounds}) || $self->{m_rounds} < 1 || $self->{m_rounds} > POSIX::INT_MAX) {
return 1;
}
return 0;
}
sub transform {
my ($self, %options) = @_;
my $transform_key;
if ($self->{type} eq KeePass2_Kdf_Argon2D) {
$transform_key = Crypt::Argon2::argon2d_raw(
$options{raw_key},
$self->{m_seed},
$self->{m_rounds},
$self->{m_memory} . 'k',
$self->{m_parallelism},
32
);
} else {
$transform_key = Crypt::Argon2::argon2i_raw(
$options{raw_key},
$self->{m_seed},
$self->{m_rounds},
$self->{m_memory} . 'k',
$self->{m_parallelism},
32
);
}
return $transform_key;
}
1;

View File

@ -0,0 +1,59 @@
package KeePass::Keys::Composite;
use strict;
use warnings;
use KeePass::constants qw(:all);
use KeePass::Keys::Password;
use KeePass::Keys::File;
use Crypt::Digest::SHA256;
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
$self->{keys} = [];
return $self;
}
sub add_key_password {
my ($self, %options) = @_;
my $key_password = KeePass::Keys::Password->new();
$key_password->set_password(password => $options{password});
push @{$self->{keys}}, $key_password;
return 0;
}
sub add_key_file {
my ($self, %options) = @_;
my $key_file = KeePass::Keys::File->new();
my ($ret, $message) = $key_file->set_keyfile(keyfile => $options{keyfile});
push @{$self->{keys}}, $key_file if ($ret == 0);
return ($ret, $message);
}
sub raw_key {
my ($self, %options) = @_;
my $raw_keys = '';
foreach my $key (@{$self->{keys}}) {
$raw_keys .= $key->raw_key();
}
if (defined($options{seed})) {
# unsupported challenge
}
return Crypt::Digest::SHA256::sha256($raw_keys);
}
sub transform {
my ($self, %options) = @_;
my $raw_keys = $self->raw_key(seed => $options{kdf}->seed());
return $options{kdf}->transform(raw_key => $raw_keys);
}
1;

View File

@ -0,0 +1,52 @@
package KeePass::Keys::File;
use strict;
use warnings;
use KeePass::constants qw(:all);
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
return $self;
}
sub slurp {
my ($self, %options) = @_;
my ($fh, $size);
if (!open($fh, '<', $options{file})) {
return (1, "Could not open $options{file}: $!");
}
if (!($size = -s $options{file})) {
return (1, "File $options{file} appears to be empty");
}
binmode $fh;
read($fh, my $buffer, $size);
close $fh;
if (length($buffer) != $size) {
$self->error(message => "Could not read entire file contents of $options{file}");
return undef;
}
return (0, undef, $buffer);
}
sub set_keyfile {
my ($self, %options) = @_;
my ($ret, $message, $buffer) = $self->slurp(file => $options{keyfile});
if ($ret == 0) {
$self->{m_key} = Crypt::Digest::SHA256::sha256($buffer);
}
return ($ret, $message);
}
sub raw_key {
my ($self, %options) = @_;
return $self->{m_key};
}
1;

View File

@ -0,0 +1,28 @@
package KeePass::Keys::Password;
use strict;
use warnings;
use KeePass::constants qw(:all);
use Crypt::Digest::SHA256;
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
return $self;
}
sub set_password {
my ($self, %options) = @_;
$self->{m_key} = Crypt::Digest::SHA256::sha256($options{password});
}
sub raw_key {
my ($self, %options) = @_;
return $self->{m_key};
}
1;

View File

@ -0,0 +1,663 @@
package KeePass::Reader;
use strict;
use warnings;
use KeePass::constants qw(:all);
use POSIX;
use Crypt::Digest::SHA256;
use Crypt::Digest::SHA512;
use Crypt::Stream::ChaCha;
use Crypt::Stream::Salsa20;
use Crypt::Mac::HMAC;
use Crypt::Mode::CBC;
use XML::LibXML::Simple;
use MIME::Base64;
use IO::Uncompress::Gunzip;
use Encode;
use KeePass::Crypto::Aes2Kdf;
use KeePass::Crypto::Argon2Kdf;
use KeePass::Keys::Composite;
our $VERSION = '0.2';
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
$self->{composite} = KeePass::Keys::Composite->new();
return $self;
}
sub error {
my ($self, %options) = @_;
if (defined($options{message})) {
$self->{error_msg} = $options{message};
}
return $self->{error_msg};
}
sub load_db {
my ($self, %options) = @_;
$self->{error_msg} = undef;
$self->{buffer_file} = undef;
$self->{master_read_pos} = 0;
$self->{buffer_file} = $self->slurp(file => $options{file});
return if (!defined($self->{buffer_file}));
return $self->read_database(password => $options{password}, keyfile => $options{keyfile});
}
sub read_database {
my ($self, %options) = @_;
my ($ret, $message);
return if ($self->read_magic_numbers());
if ($self->{sig1} == KeePass1_Signature_1 && $self->{sig2} == KeePass1_Signature_2) {
$self->error(message => "KeePass 1 database unsupported");
return ;
}
if (!($self->{sig1} == KeePass2_Signature_1 && $self->{sig2} == KeePass2_Signature_2)) {
$self->error(message => "Not a KeePass database");
return ;
}
if ($self->{version} < KeePass2_File_Version_4) {
$self->error(message => "Unsupported KeePass 2 database version (only version 4)");
return ;
}
return if ($self->keepass4_read_header_fields());
if (!defined($self->{m_master_seed}) || !defined($self->{m_encryption_iv}) || !defined($self->{cipher_mode})) {
$self->error(message => 'missing database headers');
return ;
}
my $header_sha256 = unpack('@' . $self->{master_read_pos} . ' a32', $self->{buffer_file});
$self->{master_read_pos} += 32;
my $header_hmac = unpack('@' . $self->{master_read_pos} . ' a32', $self->{buffer_file});
$self->{master_read_pos} += 32;
if (length($header_sha256) != 32 || length($header_hmac) != 32) {
$self->error(message => 'Invalid header checksum size');
return ;
}
my $header_sha256_hex = unpack('H*', $header_sha256);
my $header_hmac_hex = unpack('H*', $header_hmac);
my $header_data = unpack('a' . ($self->{end_header_pos}), $self->{buffer_file});
my $header_data_sha256_hex = Crypt::Digest::SHA256::sha256_hex($header_data);
if ($header_data_sha256_hex ne $header_sha256_hex) {
$self->error(message => 'Header SHA256 mismatch');
return ;
}
($ret, $message) = $self->{composite}->add_key_password(password => $options{password});
if ($ret) {
$self->error(message => $message);
return ;
}
if (defined($options{keyfile}) && $options{keyfile} ne '') {
($ret, $message) = $self->{composite}->add_key_file(keyfile => $options{keyfile});
if ($ret) {
$self->error(message => $message);
return ;
}
}
my $transformed_key = $self->{composite}->transform(kdf => $self->{kdf});
$self->{hmac_key} = Crypt::Digest::SHA512::sha512(
$self->{m_master_seed} . $transformed_key . pack('C', 0x01)
);
my $hmac_key = Crypt::Digest::SHA512::sha512(
pack('Q', 18446744073709551615) . $self->{hmac_key}
);
my $header_hmac_calc_hex = Crypt::Mac::HMAC::hmac_hex(
'SHA256',
$hmac_key,
$header_data
);
if ($header_hmac_hex ne $header_hmac_calc_hex) {
$self->error(message => 'Invalid credentials were provided or database file may be corrupt');
return ;
}
$self->{master_key} = Crypt::Digest::SHA256::sha256(
$self->{m_master_seed} . $transformed_key
);
return if ($self->process_blocks());
return if ($self->load_xml());
$self->unlock_passwords();
return $self->{xml};
}
sub load_xml {
my ($self, %options) = @_;
$self->{xml} = undef;
eval {
$SIG{__WARN__} = sub {};
$self->{xml} = XMLin(
$self->{xml_data},
ForceArray => ['Group', 'Entry'],
KeyAttr => []
);
};
if ($@) {
$self->error(message => 'Cannot decode xml response: $@');
return 1;
}
return 0;
}
sub browse_groups {
my ($self, %options) = @_;
return if (!defined($options{group_node}));
for (my $i = 0; $i < scalar(@{$options{group_node}}); $i++) {
if (defined($options{group_node}->[$i]->{Entry})) {
for (my $j = 0; $j < scalar(@{$options{group_node}->[$i]->{Entry}}); $j++) {
for (my $k = 0; $k < scalar(@{$options{group_node}->[$i]->{Entry}->[$j]->{String}}); $k++) {
if ($options{group_node}->[$i]->{Entry}->[$j]->{String}->[$k]->{Key} eq 'Title') {
$options{group_node}->[$i]->{Entry}->[$j]->{Title} = $options{group_node}->[$i]->{Entry}->[$j]->{String}->[$k]->{Value};
}
if ($options{group_node}->[$i]->{Entry}->[$j]->{String}->[$k]->{Key} eq 'Password' &&
defined($options{group_node}->[$i]->{Entry}->[$j]->{String}->[$k]->{Value}->{content}) &&
$options{group_node}->[$i]->{Entry}->[$j]->{String}->[$k]->{Value}->{Protected} =~ /true/i
) {
$options{group_node}->[$i]->{Entry}->[$j]->{String}->[$k]->{Value}->{content} =
$self->unlock_password(password => $options{group_node}->[$i]->{Entry}->[$j]->{String}->[$k]->{Value}->{content});
}
}
}
}
$self->browse_groups(group_node => $options{group_node}->[$i]->{Group});
}
}
sub unlock_password {
my ($self, %options) = @_;
my $password;
if ($self->{m_irs_algo} == ProtectedStreamAlgo_ChaCha20) {
$password = $self->{stream_decrypt} ->crypt(MIME::Base64::decode($options{password}));
} elsif ($self->{m_irs_algo} == ProtectedStreamAlgo_Salsa20) {
$password = $self->{stream_decrypt}->crypt(MIME::Base64::decode($options{password}));
}
return $password;
}
sub unlock_passwords {
my ($self, %options) = @_;
if ($self->{m_irs_algo} == ProtectedStreamAlgo_ChaCha20) {
my $key_iv = Crypt::Digest::SHA512::sha512($self->{m_protected_stream_key});
$self->{stream_decrypt} = Crypt::Stream::ChaCha->new(
unpack('a32', $key_iv), unpack('@32 a12', $key_iv)
);
} elsif ($self->{m_irs_algo} == ProtectedStreamAlgo_Salsa20) {
$self->{stream_decrypt} = Crypt::Stream::Salsa20->new(
Crypt::Digest::SHA256::sha256($self->{m_protected_stream_key}), Inner_Stream_Salsa20_Iv
);
}
$self->browse_groups(group_node => $self->{xml}->{Root}->{Group});
}
sub process_blocks {
my ($self, %options) = @_;
my $pos = $self->{master_read_pos};
my $payload_data = '';
while (1) {
my $block_hmac_hash_hex = unpack('H*', unpack('@' . $pos . ' a32', $self->{buffer_file}));
$pos += 32;
my $block_size = unpack('@' . $pos . ' I<', $self->{buffer_file});
$pos += 4;
if ($block_size == 0) {
last;
}
my $block_data = unpack('@' . $pos . ' a' . $block_size, $self->{buffer_file});
$pos += $block_size;
my $computed_hmac_hash_hex = Crypt::Mac::HMAC::hmac_hex(
'SHA256',
Crypt::Digest::SHA512::sha512(
pack('Q<', 0) . $self->{hmac_key}
),
pack('Q<', 0) . pack('I<', $block_size) . $block_data
);
if ($computed_hmac_hash_hex ne $block_hmac_hash_hex) {
$self->error(message => 'Payload verification failed');
return 1;
}
$payload_data .= $block_data;
}
if ($self->{cipher_mode} == Aes128_CBC || $self->{cipher_mode} == Aes256_CBC) {
my $cbc = Crypt::Mode::CBC->new('AES');
$payload_data = $cbc->decrypt($payload_data, $self->{master_key}, $self->{m_encryption_iv});
} elsif ($self->{cipher_mode} == ChaCha20) {
my $stream = Crypt::Stream::ChaCha->new($self->{master_key}, $self->{m_encryption_iv});
$payload_data = $stream->crypt($payload_data);
} elsif ($self->{cipher_mode} == Twofish_CBC) {
my $cbc = Crypt::Mode::CBC->new('Twofish');
$payload_data = $cbc->decrypt($payload_data, $self->{master_key}, $self->{m_encryption_iv});
}
if ($self->{compression_algorithm} == CompressionGZip) {
my $uncompress;
IO::Uncompress::Gunzip::gunzip(\$payload_data, \$uncompress);
$payload_data = $uncompress;
}
my $code = $self->keepass4_read_inner_fields(payload_data => $payload_data);
return $code;
}
sub read_magic_numbers {
my ($self, %options) = @_;
($self->{sig1}, $self->{sig2}, $self->{version}) = unpack('VVV', $self->{buffer_file});
if (!defined($self->{sig1}) || !defined($self->{sig2}) || !defined($self->{version})) {
$self->error(message => "Failed to read database file");
return 1;
}
$self->{master_read_pos} = 12;
return 0;
}
sub keepass_set_chipher_id {
my ($self, %options) = @_;
if (length($options{field_data}) != Uuid_Length) {
$self->error(message => "Invalid cipher uuid length:");
return 1;
}
my $uuid = unpack('H*', $options{field_data});
if ($uuid eq KeePass2_Cipher_Aes128) {
$self->{cipher_mode} = Aes128_CBC;
} elsif ($uuid eq KeePass2_Cipher_Aes256) {
$self->{cipher_mode} = Aes256_CBC;
} elsif ($uuid eq KeePass2_Cipher_Chacha20) {
$self->{cipher_mode} = ChaCha20;
} elsif ($uuid eq KeePass2_Cipher_Twofish) {
$self->{cipher_mode} = Twofish_CBC;
}
if (!defined($self->{cipher_mode})) {
$self->error(message => 'Unsupported cipher');
return 1;
}
return 0;
}
sub keepass_set_kdf {
my ($self, %options) = @_;
my $map = $self->keepass2_read_variant_map(field_data => $options{field_data});
return 1 if (!defined($map));
if (!defined($map->{'$UUID'}) || length($map->{'$UUID'}) != Uuid_Length) {
$self->error(message => 'Unsupported key derivation function (KDF) or invalid parameters');
return 1;
}
my $kdf_uuid = unpack('H*', $map->{'$UUID'});
if ($kdf_uuid eq KeePass2_Kdf_Aes_Kdbx3) {
$kdf_uuid = KeePass2_Kdf_Aes_Kdbx4;
}
if ($kdf_uuid eq KeePass2_Kdf_Argon2D) {
$self->{kdf} = KeePass::Crypto::Argon2Kdf->new(type => KeePass2_Kdf_Argon2D);
} elsif ($kdf_uuid eq KeePass2_Kdf_Argon2Id) {
$self->{kdf} = KeePass::Crypto::Argon2Kdf->new(type => KeePass2_Kdf_Argon2Id);
} else {
# KeePass2_Kdf_Aes_Kdbx4: we don't support it. please use Argon2
$self->error(message => 'Unsupported key derivation function (KDF) or invalid parameters');
return 1;
}
if ($self->{kdf}->process_parameters(params => $map)) {
$self->error(message => 'Unsupported key derivation function (KDF) or invalid parameters');
return 1;
}
return 0;
}
sub keepass_set_compression_flags {
my ($self, %options) = @_;
if (length($options{field_data}) != 4) {
$self->error(message => 'Invalid compression flags length');
return 1;
}
my $id = unpack('V', $options{field_data});
if ($id > CompressionAlgorithmMax) {
$self->error(message => 'Unsupported compression algorithm');
return 1;
}
$self->{compression_algorithm} = $id;
return 0;
}
sub keepass4_read_inner_fields {
my ($self, %options) = @_;
$self->{xml_data} = undef;
$self->{m_protected_stream_key} = undef;
$self->{m_irs_algo} = undef;
my $pos = 0;
while (1) {
my ($field_id, $field_len) = unpack('@' . $pos . ' CV', $options{payload_data});
if (!defined($field_id)) {
$self->error(message => 'Invalid inner header id size');
return 1;
}
if (!defined($field_len)) {
$self->error(message => 'Invalid inner header field length');
return 1;
}
$pos += 5;
my $field_data;
if ($field_len > 0) {
$field_data = unpack('@' . $pos . ' a' . $field_len, $options{payload_data});
if (!defined($field_data) || length($field_data) != $field_len) {
$self->error(message => "Invalid inner header data length");
return 1;
}
$pos += $field_len;
}
if ($field_id == KeePass2_InnerHeaderFieldID_End) {
last;
} elsif ($field_id == KeePass2_InnerHeaderFieldID_InnerRandomStreamID) {
if (length($field_data) != 4) {
$self->error(message => 'Invalid random stream id size');
return 1;
}
my $field_data = unpack('V', $field_data);
if ($field_data != ProtectedStreamAlgo_Salsa20 && $field_data != ProtectedStreamAlgo_ChaCha20) {
$self->error(message => 'Invalid inner random stream cipher');
return 1;
}
$self->{m_irs_algo} = $field_data;
} elsif ($field_id == KeePass2_InnerHeaderFieldID_InnerRandomStreamKey) {
$self->{m_protected_stream_key} = $field_data;
} elsif ($field_id == KeePass2_InnerHeaderFieldID_Binary) {
if ($field_len < 1) {
$self->error(message => 'Invalid inner header binary size');
return 1;
}
# not supported binary attachment
}
}
$self->{xml_data} = unpack('@' . $pos . ' a*', $options{payload_data});
return 0;
}
sub keepass4_read_header_fields {
my ($self, %options) = @_;
$self->{start_header_pos} = $self->{master_read_pos};
$self->{compression_algorithm} = CompressionNone;
$self->{header_comment} = undef;
$self->{m_encryption_iv} = undef;
$self->{m_master_seed} = undef;
$self->{cipher_mode} = undef;
while (1) {
my ($field_id, $field_len) = unpack('@' . $self->{master_read_pos} . ' CV', $self->{buffer_file});
if (!defined($field_id)) {
$self->error(message => "Invalid header id size");
return 1;
}
if (!defined($field_len)) {
$self->error(message => "Invalid header field length");
return 1;
}
$self->{master_read_pos} += 5;
my $field_data;
if ($field_len > 0) {
$field_data = unpack('@' . $self->{master_read_pos} . ' a' . $field_len, $self->{buffer_file});
if (!defined($field_data) || length($field_data) != $field_len) {
$self->error(message => "Invalid header data length");
return 1;
}
$self->{master_read_pos} += $field_len;
}
if ($field_id == KeePass2_HeaderFieldID_EndOfHeader) {
last;
} elsif ($field_id == KeePass2_HeaderFieldID_Comment) {
} elsif ($field_id == KeePass2_HeaderFieldID_CipherID) {
return 1 if ($self->keepass_set_chipher_id(field_data => $field_data));
} elsif ($field_id == KeePass2_HeaderFieldID_CompressionFlags) {
return 1 if ($self->keepass_set_compression_flags(field_data => $field_data));
} elsif ($field_id == KeePass2_HeaderFieldID_EncryptionIV) {
$self->{m_encryption_iv} = $field_data;
} elsif ($field_id == KeePass2_HeaderFieldID_MasterSeed) {
if (length($field_data) != 32) {
$self->error(message => "Invalid master seed size");
return 1;
}
$self->{m_master_seed} = $field_data;
} elsif ($field_id == KeePass2_HeaderFieldID_KdfParameters) {
return 1 if ($self->keepass_set_kdf(field_data => $field_data));
} elsif ($field_id == KeePass2_HeaderFieldID_PublicCustomData) {
} elsif (
$field_id == KeePass2_HeaderFieldID_ProtectedStreamKey ||
$field_id == KeePass2_HeaderFieldID_TransformRounds ||
$field_id == KeePass2_HeaderFieldID_TransformSeed ||
$field_id == KeePass2_HeaderFieldID_StreamStartBytes ||
$field_id == KeePass2_HeaderFieldID_InnerRandomStreamID
) {
$self->error(message => "Legacy header fields found in KDBX4 file");
return 1;
}
}
$self->{end_header_pos} = $self->{master_read_pos};
return 0;
}
sub keepass2_read_variant_map {
my ($self, %options) = @_;
my $map = {};
my $pos = 0;
my $version = unpack('v', $options{field_data});
my $max_version = VariantMap_Version & VariantMap_Critical_Mask;
if (!defined($version) || ($version > $max_version)) {
$self->error(message => "Unsupported KeePass variant map version");
return undef;
}
$pos += 2;
while (1) {
my $field_type = ord(unpack('@' . $pos . ' a', $options{field_data}));
$pos++;
if (!defined($field_type)) {
$self->error(message => 'Invalid variant map field type size');
return undef;
}
if ($field_type == VariantMapFieldType_End) {
last;
}
my $name_len = unpack('@' . $pos . ' V', $options{field_data});
$pos += 4;
if (!defined($name_len)) {
$self->error(message => 'Invalid variant map entry name length');
return undef;
}
my $name_data = unpack('@' . $pos . ' a' . $name_len, $options{field_data});
$pos += $name_len;
if (!defined($name_data) || length($name_data) != $name_len) {
$self->error(message => 'Invalid variant map entry name data');
return undef;
}
$name_data = Encode::decode('UTF-8', $name_data);
my $value_len = unpack('@' . $pos . ' V', $options{field_data});
$pos += 4;
if (!defined($value_len)) {
$self->error(message => 'Invalid variant map entry value length');
return undef;
}
my $value_data = unpack('@' . $pos . ' a' . $value_len, $options{field_data});
$pos += $value_len;
if (!defined($value_data) || length($value_data) != $value_len) {
$self->error(message => 'Invalid variant map entry value data');
return undef;
}
if ($field_type == VariantMapFieldType_UInt64) {
$map->{$name_data} = unpack('Q', $value_data);
} elsif ($field_type == VariantMapFieldType_UInt32) {
$map->{$name_data} = unpack('V', $value_data);
} elsif ($field_type == VariantMapFieldType_Int32) {
$map->{$name_data} = unpack('l', $value_data);
} elsif ($field_type == VariantMapFieldType_Int64) {
$map->{$name_data} = unpack('q', $value_data);
} elsif ($field_type == VariantMapFieldType_String) {
$map->{$name_data} = Encode::decode('UTF-8', $value_data);
} elsif ($field_type == VariantMapFieldType_ByteArray) {
$map->{$name_data} = $value_data;
} else {
$self->error(message => 'Invalid variant map entry type');
return undef;
}
}
return $map;
}
sub slurp {
my ($self, %options) = @_;
my ($fh, $size);
if (!open($fh, '<', $options{file})) {
$self->error(message => "Could not open $options{file}: $!");
return undef;
}
if (!($size = -s $options{file})) {
$self->error(message => "File $options{file} appears to be empty");
return undef;
}
binmode $fh;
read($fh, my $buffer, $size);
close $fh;
if (length($buffer) != $size) {
$self->error(message => "Could not read entire file contents of $options{file}");
return undef;
}
return $buffer;
}
1;
__END__
=head1 NAME
KeePass::Reader - Interface to KeePass V4 database files
=head1 SYNOPSIS
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use KeePass::Reader;
my $keepass = KeePass::Reader->new();
my $content = $keepass->load_db(file => './files/test1.kdbx', password => 'test');
my $error = $keepass->error();
if (defined($error)) {
print "error: $error\n";
}
print Data::Dumper::Dumper($content);
exit(0);
=head1 DESCRIPTION
C<KeePass::Reader> is a perl interface to read KeePass version 4.
It supports following capabilities:
- Encryption Algorithm: AES, TwoFish, ChaCha20
- Key Derivation Function: Argon2
- Keys: Password, KeyFile (SHA-256 hash of the key file)
=head1 METHODS
=over 4
=item new
Create new object:
my $keepass = KeePass::Reader->new();
=item load_db ([ OPTIONS ])
Read a kdbx filename. Returns hash structure on success (otherwise undef).
C<OPTIONS> are passed in a hash like fashion, using key and value pairs. Possible options are:
B<file> - Set the kdbx filename to read.
B<password> - Set the password credential.
B<keyfile> - Set the key filename (optional).
=item error ( )
Returns the last error message. returns undef if no error.
=back
=head1 LICENSE
This library is licensed under the Apache License 2.0. Details of this license can be found within the 'LICENSE' text file
=head1 AUTHOR
Quentin Garnier <qgarnier@centreon.com>
=cut

View File

@ -0,0 +1,106 @@
package KeePass::constants;
use strict;
use warnings;
use base qw(Exporter);
my %constants;
BEGIN {
%constants = (
KeePass1_Signature_1 => 0x9AA2D903,
KeePass1_Signature_2 => 0xB54BFB65,
KeePass2_Signature_1 => 0x9AA2D903,
KeePass2_Signature_2 => 0xB54BFB67,
KeePass2_File_Version_4 => 0x00040000,
KeePass2_File_Version_3_1 => 0x00030001,
KeePass2_File_Version_3 => 0x00030000,
KeePass2_File_Version_2 => 0x00020000,
KeePass2_HeaderFieldID_EndOfHeader => 0,
KeePass2_HeaderFieldID_Comment => 1,
KeePass2_HeaderFieldID_CipherID => 2,
KeePass2_HeaderFieldID_CompressionFlags => 3,
KeePass2_HeaderFieldID_MasterSeed => 4,
KeePass2_HeaderFieldID_TransformSeed => 5,
KeePass2_HeaderFieldID_TransformRounds => 6,
KeePass2_HeaderFieldID_EncryptionIV => 7,
KeePass2_HeaderFieldID_ProtectedStreamKey => 8,
KeePass2_HeaderFieldID_StreamStartBytes => 9,
KeePass2_HeaderFieldID_InnerRandomStreamID => 10,
KeePass2_HeaderFieldID_KdfParameters => 11,
KeePass2_HeaderFieldID_PublicCustomData => 12,
KeePass2_InnerHeaderFieldID_End => 0,
KeePass2_InnerHeaderFieldID_InnerRandomStreamID => 1,
KeePass2_InnerHeaderFieldID_InnerRandomStreamKey => 2,
KeePass2_InnerHeaderFieldID_Binary => 3,
Uuid_Length => 16,
KeePass2_Cipher_Aes128 => '61ab05a1946441c38d743a563df8dd35',
KeePass2_Cipher_Aes256 => '31c1f2e6bf714350be5805216afc5aff',
KeePass2_Cipher_Twofish => 'ad68f29f576f4bb9a36ad47af965346c',
KeePass2_Cipher_Chacha20 => 'd6038a2b8b6f4cb5a524339a31dbb59a',
KeePass2_Kdf_Aes_Kdbx3 => 'c9d9f39a628a4460bf740d08c18a4fea',
KeePass2_Kdf_Aes_Kdbx4 => '7c02bb8279a74ac0927d114a00648238',
KeePass2_Kdf_Argon2D => 'ef636ddf8c29444b91f7a9a403e30a0c',
KeePass2_Kdf_Argon2Id => '9e298b1956db4773b23dfc3ec6f0a1e6',
Aes128_CBC => 1,
Aes256_CBC => 2,
ChaCha20 => 3,
Twofish_CBC => 4,
VariantMap_Version => 0x0100,
VariantMap_Critical_Mask => 0xFF00,
VariantMapFieldType_End => 0,
VariantMapFieldType_Byte => 2, #0x02,
VariantMapFieldType_UInt16 => 3, #0x03,
VariantMapFieldType_UInt32 => 4, #0x04,
VariantMapFieldType_UInt64 => 5, #0x05,
VariantMapFieldType_SByte => 10, #0x0A,
VariantMapFieldType_Int16 => 11, #0x0B,
VariantMapFieldType_Int32 => 12, #0x0C,
VariantMapFieldType_Int64 => 13, #0x0D,
VariantMapFieldType_Float => 16, #0x10,
VariantMapFieldType_Double => 17, #0x11,
VariantMapFieldType_Decimal => 18, #0x12,
VariantMapFieldType_Char => 23, #0x17,
VariantMapFieldType_String => 24, #0x18,
VariantMapFieldType_ByteArray => 66, #0x42
KdfParam_Aes_Rounds => 'R',
KdfParam_Aes_Seed => 'S',
KdfParam_Argon2_Salt => 'S',
KdfParam_Argon2_Parallelism => 'P',
KdfParam_Argon2_Memory => 'M',
KdfParam_Argon2_Iterations => 'I',
KdfParam_Argon2_Version => 'V',
KdfParam_Argon2_Secret => 'K',
KdfParam_Argon2_Assocdata => 'A',
Kdf_Min_Seed_Size => 8,
Kdf_Max_Seed_Size => 32,
CompressionNone => 0,
CompressionGZip => 1,
CompressionAlgorithmMax => 1,
ProtectedStreamAlgo_ArcFourVariant => 1,
ProtectedStreamAlgo_Salsa20 => 2,
ProtectedStreamAlgo_ChaCha20 => 3,
Inner_Stream_Salsa20_Iv => 0xe8 . 0x30 . 0x09 . 0x4b . 0x97 . 0x20 . 0x5d . 0x2a
);
}
use constant \%constants;
our @EXPORT;
our @EXPORT_OK = keys %constants;
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
1;

View File

@ -0,0 +1,64 @@
name: "@NAME@"
arch: "${ARCH}"
platform: "linux"
version_schema: "none"
version: "0.8"
release: "3${DIST}"
section: "default"
priority: "optional"
maintainer: "Centreon <contact@centreon.com>"
description: |
Perl interface to the libssh library
Commit: @COMMIT_HASH@
vendor: "Centreon"
homepage: "https://www.centreon.com"
license: "Apache-2.0"
contents:
- src: "/tmp/lib/perl5/*/auto/Libssh/Session/Session.so"
dst: "@PERL_VENDORARCH@/auto/Libssh/Session/"
file_info:
mode: 0644
- src: "/tmp/lib/perl5/*/Libssh/"
dst: "@PERL_VENDORARCH@/Libssh/"
file_info:
mode: 0644
- src: "/tmp/man/man3/Libssh::*"
dst: "/usr/share/man/man3/"
file_info:
mode: 0644
overrides:
rpm:
depends:
- perl
- libssh
conflicts:
- perl-Libssh-Session-debuginfo
replaces:
- perl-Libssh-Session-debuginfo
provides:
- perl-Libssh-Session-debuginfo
- perl(Libssh::Session)
- perl(Libssh::Sftp)
deb:
depends:
- perl
- libc6
- libssh-4
conflicts:
- libssh-session-perl-dbgsym
replaces:
- libssh-session-perl-dbgsym
provides:
- libssh-session-perl-dbgsym
- libssh-session-sftp
rpm:
summary: Perl interface to the libssh library
compression: zstd
signature:
key_file: ${RPM_SIGNING_KEY_FILE}
key_id: ${RPM_SIGNING_KEY_ID}

View File

@ -0,0 +1,78 @@
name: "@NAME@"
arch: "${ARCH}"
platform: "linux"
version_schema: "none"
version: "0.54"
release: "2${DIST}"
section: "default"
priority: "optional"
maintainer: "Centreon <contact@centreon.com>"
description: |
Net::Curl provides a Perl interface to libcurl created with object-oriented implementations in mind.
This documentation contains Perl-specific details and quirks.
For more information consult libcurl man pages and documentation at http://curl.haxx.se.
Commit: @COMMIT_HASH@
vendor: "Centreon"
homepage: "https://www.centreon.com"
license: "Apache-2.0"
contents:
- src: "/tmp/lib/perl5/*/auto/Net/Curl/Curl.so"
dst: "@PERL_VENDORARCH@/auto/Net/Curl/"
file_info:
mode: 0644
- src: "/tmp/lib/perl5/*/Net/Curl.pm"
dst: "@PERL_VENDORARCH@/Net/"
file_info:
mode: 0644
- src: "/tmp/lib/perl5/*/Net/Curl/"
dst: "@PERL_VENDORARCH@/Net/Curl/"
file_info:
mode: 0644
- src: "/tmp/man/man3/Net::Curl*"
dst: "/usr/share/man/man3/"
file_info:
mode: 0644
overrides:
rpm:
depends:
- perl
- libcurl
conflicts:
- perl-Net-Curl-debuginfo
replaces:
- perl-Net-Curl-debuginfo
provides:
- perl-Net-Curl-debuginfo
- perl(Net::Curl)
- perl(Net::Curl::Compat)
- perl(Net::Curl::Easy)
- perl(Net::Curl::Form)
- perl(Net::Curl::Share)
- perl(Net::Curl::Multi)
deb:
depends:
- perl
- libcurl4
conflicts:
- libnet-curl-perl-dbgsym
replaces:
- libnet-curl-perl-dbgsym
provides:
- libnet-curl-perl-dbgsym
- libnet-curl-compat-perl
- libnet-curl-easy-perl
- libnet-curl-form-perl
- libnet-curl-share-perl
- libnet-curl-multi-perl
rpm:
summary: Perl interface for libcurl
compression: zstd
signature:
key_file: ${RPM_SIGNING_KEY_FILE}
key_id: ${RPM_SIGNING_KEY_ID}

View File

@ -0,0 +1,45 @@
%define archive_name putty
Name: plink
Version: 0.74
Release: 1%{?dist}
Summary: Plink (PuTTY Link) is a command-line connection tool similar to UNIX ssh.
Group: Development/Tools
License: MIT licence
URL: http://www.chiark.greenend.org.uk/~sgtatham/putty/
Source0: %{archive_name}-%{version}.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{archive_name}-%{version}-%{release}-XXXXXX)
BuildRequires: make
BuildRequires: gcc
%description
Plink (PuTTY Link) is a command-line connection tool similar to UNIX ssh.
It is mostly used for automated operations, such as making CVS access a repository on a remote server.
%prep
%setup -q -n %{archive_name}-%{version}
%build
%configure --without-gtk
make %{?_smp_mflags}
%install
rm -rf %{buildroot}
make install DESTDIR=%{buildroot}
rm -rf $RPM_BUILD_ROOT%{_bindir}/pscp
rm -rf $RPM_BUILD_ROOT%{_bindir}/psftp
rm -rf $RPM_BUILD_ROOT%{_bindir}/puttygen
rm -rf $RPM_BUILD_ROOT%{_mandir}/
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%doc
%{_bindir}/plink
%changelog