working commit

This commit is contained in:
2026-05-26 17:11:13 +02:00
commit 2e59f88d76
103 changed files with 18276 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
#!/bin/sh
MAX_SIZE=1024 # 1 MB limit in KB
for file in $(git diff --cached --name-only --diff-filter=ACM); do
if [ ! -e "$file" ]; then continue; fi
size=$(du -k "$file" | cut -f1)
if [ $size -gt $MAX_SIZE ]; then
echo "Error: File $file is larger than the allowed size of $((MAX_SIZE / 1024)) MB."
exit 1
fi
done
status=0
for file in $(git diff --cached --name-only | grep -E '\.go$'); do
badfile=$(gofmt -l "$file")
if test -n "$badfile" ; then
echo "Error: file needs gofmt: $badfile"
status=1
fi
done
# If any files were not formatted, exit with a non-zero status to abort the commit.
if [ "$status" -ne 0 ]; then
echo "git pre-commit check failed: some Go files are not formatted."
exit 1
fi
exit 0
+24
View File
@@ -0,0 +1,24 @@
*~
autom4te.cache
Makefile
config.status
config.log
cmd/mbased/mbased
cmd/mbasectl/mbasectl
*.db
*.db-shm
*.db-wal
*.tar.*
*.tmp.*
*.tar
*.bin
tmp
mbased
mbasectl
DIST
*.tar.gz
*.deb
*.rpm
mbased.service
variant.go
initrc/mbased
+26
View File
@@ -0,0 +1,26 @@
FROM alpine:3.23 AS builder
RUN apk --no-cache add make binutils gcc libc-dev automake autoconf curl
RUN curl -o /usr/local/lib/go.tar.gz https://dl.google.com/go/go1.26.2.linux-amd64.tar.gz
RUN cd /usr/local/lib && tar xzf go.tar.gz
RUN cd /usr/local/bin && ln -sf ../lib/go/bin/* .
WORKDIR /app/src/
COPY go.mod go.sum .
COPY . .
RUN ./configure --prefix=/app
RUN make all install
RUN make clean
RUN rm -rf /app/src
FROM alpine:3.23 AS runner
COPY --from=builder /app /app
RUN chmod 1777 /var
RUN mkdir -p /app/etc/mbase
RUN touch /app/etc/mbase/mbased.yaml
WORKDIR /app
#USER daemon:daemon
ENTRYPOINT ["/app/sbin/mbased", "--asDaemon=false"]
+439
View File
@@ -0,0 +1,439 @@
Attribution-NonCommercial-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International Public License
("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-NC-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution, NonCommercial, and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. NonCommercial means not primarily intended for or directed towards
commercial advantage or monetary compensation. For purposes of
this Public License, the exchange of the Licensed Material for
other material subject to Copyright and Similar Rights by digital
file-sharing or similar means is NonCommercial provided there is
no payment of monetary compensation in connection with the
exchange.
l. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
m. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
n. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part, for NonCommercial purposes only; and
b. produce, reproduce, and Share Adapted Material for
NonCommercial purposes only.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties, including when
the Licensed Material is used other than for NonCommercial
purposes.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-NC-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database for NonCommercial purposes
only;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
+186
View File
@@ -0,0 +1,186 @@
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
SUBDIRS = mans
GOFLAGS= -v
bin_PROGRAMS = mproxyctl
sbin_PROGRAMS = mproxyd
mproxyctl_SOURCES = \
cmd/mproxyctl/main.go
EXTRA_mproxyctl_SOURCES = \
cmd/mproxyctl/util/util.go
mproxyd_SOURCES = cmd/mproxyd/main.go
EXTRA_mproxyd_SOURCES = cmd/mproxyd/starter/starter.go
mproxyctl$(EXEEXT): $(mproxyctl_SOURCES) $(EXTRA_mproxyctl_SOURCES) $(EXTRA_mbased_SOURCES)
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o mproxyctl$(EXEEXT) $(mproxyctl_SOURCES)
mproxyd$(EXEEXT): $(mproxyd_SOURCES) $(EXTRA_mproxyd_SOURCES)
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mproxyd$(EXEEXT) $(mproxyd_SOURCES)
run: $(mproxyd_SOURCES)
cd cmd/mproxyd && env CGO_ENABLED=1 $(GO) run . --asDaemon=false --port=443
CWD=$(shell pwd)
EXTRA_mproxyd_SOURCES += \
app/config/config.go \
app/config/variant.go \
app/handler/aaafunc.go \
app/handler/account.go \
app/handler/grant.go \
app/handler/handler.go \
app/handler/notfound.go \
app/handler/response.go \
app/handler/service.go \
app/locker/locker.go \
app/logger/logger.go \
app/router/bindobj.go \
app/router/context.go \
app/router/corsmw.go \
app/router/loggingmw.go \
app/router/pathc.go \
app/router/recovermw.go \
app/router/router.go \
app/server/server.go \
app/server/listen.go \
app/service/service.go \
\
app/servoper/operator.go \
app/servoper/service.go \
\
pkg/auxhttp/basic.go \
pkg/auxhttp/crange.go \
pkg/auxpwd/passwd.go \
pkg/auxtool/cleandir.go \
pkg/auxtool/fileex.go \
pkg/auxtool/randstr.go \
pkg/auxtool/tmpfile.go \
pkg/auxtool/unixnow.go \
pkg/auxutar/utar.go \
pkg/auxuuid/uuid.go \
pkg/auxx509/x509cert.go \
pkg/terms/terms.go
EXTRA_DIST = vendor/* \
\
Containerfile \
go.mod \
go.sum \
LICENSE.txt \
README.md \
DEVEL.md \
\
debian/changelog.in \
debian/compat \
debian/control.in \
debian/files \
debian/.gitignore \
debian/mproxy-control.install \
debian/mproxy-control.postinst \
debian/mproxy-control.postrm \
debian/mproxy-control.preinst \
debian/mproxy-control.prerm \
debian/mproxy-service.install \
debian/mproxy-service.postinst \
debian/mproxy-service.postrm \
debian/mproxy-service.preinst \
debian/mproxy-service.prerm \
debian/patches/series \
debian/README.Debian \
debian/rules \
debian/source/format \
debian/source/include-binaries \
debian/watch \
\
initrc/.gitignore \
initrc/mproxyd.in \
initrc/mproxyd.service.in \
\
app/router/pathc_test.go \
app/router/router_test.go \
pkg/auxpwd/passwd_test.go \
pkg/auxx509/x509cert_test.go
format:
@dirs=$$($(FIND) $(CWD)/app $(CWD)/cmd $(CWD)/pkg \
-name '*.go' | $(XARGS) -n1 dirname | $(SORT) | $(UNIQ)); \
for dir in $$dirs;do \
(echo "====$$dir===="; cd $$dir && $(GO) fmt .); \
done
DIST_DIR= $(shell pwd)/DIST
BUILD_DIR= $(shell pwd)/BUILD
IMAGE_REPO = localhost
IMAGE_NAME = $(PACKAGE_NAME):$(PACKAGE_VERSION)
IMAGE_TARNAME = $(PACKAGE_NAME)-$(PACKAGE_VERSION).img
IMAGE_CONTAINERFILE = Containerfile
image:: build-image
build-image: clean
# $(GO) mod vendor
mkdir -p $(DIST_DIR)
$(SUDO) $(PODMAN) build -t $(IMAGE_REPO)/$(IMAGE_NAME) -f $(IMAGE_CONTAINERFILE) .
rm -f $(DIST_DIR)/$(IMAGE_TARNAME)
$(SUDO) $(PODMAN) image save $(IMAGE_REPO)/$(IMAGE_NAME) --format oci-archive \
-o $(DIST_DIR)/$(IMAGE_TARNAME)
username=$$(whoami); \
$(SUDO) chown $$username $(DIST_DIR)/$(IMAGE_TARNAME)
# rm -rf vendor
$(DIST_ARCHIVES): dist
package:: debian-package
debian-package: $(DIST_ARCHIVES)
mkdir -p $(BUILD_DIR)
mv $(DIST_ARCHIVES) $(BUILD_DIR)
cd $(BUILD_DIR) && $(AMTAR) -xf $(DIST_ARCHIVES)
cd $(BUILD_DIR)/$(distdir) && ./configure --prefix=/usr
cd $(BUILD_DIR)/$(distdir) && $(MAKE) clean
cd $(BUILD_DIR)/$(distdir) && $(DPKGSOURCE) -i --before-build .
cd $(BUILD_DIR)/$(distdir) && $(DBUILDPACKAGE) -nc -us -uc -ui -i -b
mkdir -p $(DIST_DIR)
$(CP) $(BUILD_DIR)/*.deb $(DIST_DIR)
rm -rf $(BUILD_DIR)
FREEBSD_LOCALBASE = /usr/local
FREEBSD_RCDIR = $(FREEBSD_LOCALBASE)/etc/rc.d
LINUX_SYSTEMDDIR = /lib/systemd/system
install-data-local:
test -z $(DESTDIR)$(srv_confdir) || $(MKDIR_P) $(DESTDIR)$(srv_confdir)
test -z $(DESTDIR)$(srv_logdir) || $(MKDIR_P) $(DESTDIR)$(srv_logdir)
test -z $(DESTDIR)$(srv_rundir) || $(MKDIR_P) $(DESTDIR)$(srv_rundir)
test -z $(DESTDIR)$(srv_datadir) || $(MKDIR_P) $(DESTDIR)$(srv_datadir)
if FREEBSD_OS
test -z $(DESTDIR)$(FREEBSD_RCDIR) || $(MKDIR_P) $(DESTDIR)$(FREEBSD_RCDIR)
$(INSTALL_DATA) initrc/mproxyd $(DESTDIR)$(FREEBSD_RCDIR)
chmod a+x $(DESTDIR)$(FREEBSD_RCDIR)/mproxyd
endif
if LINUX_OS
if SYSTEMD
test -z $(DESTDIR)$(LINUX_SYSTEMDDIR) || $(MKDIR_P) $(DESTDIR)$(LINUX_SYSTEMDDIR)
$(INSTALL_DATA) initrc/mproxyd.service $(DESTDIR)$(LINUX_SYSTEMDDIR)
endif
endif
clean-local:
$(FIND) $(CWD) -name '*~' | $(XARGS) rm -f
rm -rf autom4te.cache
rm -f cmd/mproxyd/mproxyd
rm -f cmd/mproxyctl/mproxyctl
# rm -rf tmp/
distclean-local:
rm -rf autom4te.cache
rm -rf $(DIST_DIR)
rm -rf tmp/
+1081
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
# mproxy
Vendored
+977
View File
@@ -0,0 +1,977 @@
# generated automatically by aclocal 1.17 -*- Autoconf -*-
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.72],,
[m4_warning([this file was generated for autoconf 2.72.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.17'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.17], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.17])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
# therefore $ac_aux_dir as well) can be either absolute or relative,
# depending on how configure is run. This is pretty annoying, since
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
# source directory, any form will work fine, but in subdirectories a
# relative path needs to be adjusted first.
#
# $ac_aux_dir/missing
# fails when called from a subdirectory if $ac_aux_dir is relative
# $top_srcdir/$ac_aux_dir/missing
# fails if $ac_aux_dir is absolute,
# fails when called from a subdirectory in a VPATH build with
# a relative $ac_aux_dir
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
# harmless because $srcdir is '.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
# and then we would define $MISSING as
# MISSING="\${SHELL} $am_aux_dir/missing"
# This will work as long as MISSING is not called from configure, because
# unfortunately $(top_srcdir) has no meaning in configure.
# However there are other variables, like CC, which are often used in
# configure, and could therefore not use this "fixed" $ac_aux_dir.
#
# Another solution, used here, is to always expand $ac_aux_dir to an
# absolute PATH. The drawback is that using absolute paths prevent a
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
# Expand $ac_aux_dir to an absolute path.
am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ([2.52])dnl
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
m4_define([_AM_COND_VALUE_$1], [$2])dnl
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([[conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.]])
fi])])
# AM_EXTRA_RECURSIVE_TARGETS -*- Autoconf -*-
# Copyright (C) 2012-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_EXTRA_RECURSIVE_TARGETS
# --------------------------
# Define the list of user recursive targets. This macro exists only to
# be traced by Automake, which will ensure that a proper definition of
# user-defined recursive targets (and associated rules) is propagated
# into all the generated Makefiles.
# TODO: We should really reject non-literal arguments here...
AC_DEFUN([AM_EXTRA_RECURSIVE_TARGETS], [])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])
[_AM_PROG_CC_C_O
])
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
# -----------------------------------------------
# The call with PACKAGE and VERSION arguments is the old style
# call (pre autoconf-2.50), which is being phased out. PACKAGE
# and VERSION should now be passed to AC_INIT and removed from
# the call to AM_INIT_AUTOMAKE.
# We support both call styles for the transition. After
# the next Automake release, Autoconf can make the AC_INIT
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.65])dnl
m4_ifdef([_$0_ALREADY_INIT],
[m4_fatal([$0 expanded multiple times
]m4_defn([_$0_ALREADY_INIT]))],
[m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
AC_REQUIRE([AC_PROG_INSTALL])dnl
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[AC_DIAGNOSE([obsolete],
[$0: two- and three-arguments forms are deprecated.])
m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(
m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
[ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
AM_MISSING_PROG([AUTOCONF], [autoconf])
AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
AM_MISSING_PROG([AUTOHEADER], [autoheader])
AM_MISSING_PROG([MAKEINFO], [makeinfo])
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target (and possibly the TAP driver). The
# system "awk" is bad on some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES([CC])],
[m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES([CXX])],
[m4_define([AC_PROG_CXX],
m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES([OBJC])],
[m4_define([AC_PROG_OBJC],
m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[_AM_DEPENDENCIES([OBJCXX])],
[m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
# Variables for tags utilities; see am/tags.am
if test -z "$CTAGS"; then
CTAGS=ctags
fi
AC_SUBST([CTAGS])
if test -z "$ETAGS"; then
ETAGS=etags
fi
AC_SUBST([ETAGS])
if test -z "$CSCOPE"; then
CSCOPE=cscope
fi
AC_SUBST([CSCOPE])
AC_REQUIRE([_AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
AC_REQUIRE([_AM_PROG_RM_F])
AC_REQUIRE([_AM_PROG_XARGS_N])
dnl The trailing newline in this macro's definition is deliberate, for
dnl backward compatibility and to allow trailing 'dnl'-style comments
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
])
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp files are numbered to have different names.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[# Compute $1's index in $config_headers.
_am_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
if test x"${install_sh+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
[rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
[AC_REQUIRE([AM_MISSING_HAS_RUN])
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it is modern enough.
# If it is, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
am_missing_run="$MISSING "
else
am_missing_run=
AC_MSG_WARN(['missing' script is too old or missing])
fi
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
# --------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
# _AM_SET_OPTIONS(OPTIONS)
# ------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
# -------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 2022-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_PROG_RM_F
# ---------------
# Check whether 'rm -f' without any arguments works.
# https://bugs.gnu.org/10828
AC_DEFUN([_AM_PROG_RM_F],
[am__rm_f_notfound=
AS_IF([(rm -f && rm -fr && rm -rf) 2>/dev/null], [], [am__rm_f_notfound='""'])
AC_SUBST(am__rm_f_notfound)
])
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_RUN_LOG(COMMAND)
# -------------------
# Run COMMAND, save the exit status in ac_status, and log it.
# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
AC_DEFUN([AM_RUN_LOG],
[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
(exit $ac_status); }])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_SLEEP_FRACTIONAL_SECONDS
# ----------------------------
AC_DEFUN([_AM_SLEEP_FRACTIONAL_SECONDS], [dnl
AC_CACHE_CHECK([whether sleep supports fractional seconds],
am_cv_sleep_fractional_seconds, [dnl
AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=yes],
[am_cv_sleep_fractional_seconds=no])
])])
# _AM_FILESYSTEM_TIMESTAMP_RESOLUTION
# -----------------------------------
# Determine the filesystem's resolution for file modification
# timestamps. The coarsest we know of is FAT, with a resolution
# of only two seconds, even with the most recent "exFAT" extensions.
# The finest (e.g. ext4 with large inodes, XFS, ZFS) is one
# nanosecond, matching clock_gettime. However, it is probably not
# possible to delay execution of a shell script for less than one
# millisecond, due to process creation overhead and scheduling
# granularity, so we don't check for anything finer than that. (See below.)
AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl
AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS])
AC_CACHE_CHECK([filesystem timestamp resolution],
am_cv_filesystem_timestamp_resolution, [dnl
# Default to the worst case.
am_cv_filesystem_timestamp_resolution=2
# Only try to go finer than 1 sec if sleep can do it.
# Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work,
# - 1 sec is not much of a win compared to 2 sec, and
# - it takes 2 seconds to perform the test whether 1 sec works.
#
# Instead, just use the default 2s on platforms that have 1s resolution,
# accept the extra 1s delay when using $sleep in the Automake tests, in
# exchange for not incurring the 2s delay for running the test for all
# packages.
#
am_try_resolutions=
if test "$am_cv_sleep_fractional_seconds" = yes; then
# Even a millisecond often causes a bunch of false positives,
# so just try a hundredth of a second. The time saved between .001 and
# .01 is not terribly consequential.
am_try_resolutions="0.01 0.1 $am_try_resolutions"
fi
# In order to catch current-generation FAT out, we must *modify* files
# that already exist; the *creation* timestamp is finer. Use names
# that make ls -t sort them differently when they have equal
# timestamps than when they have distinct timestamps, keeping
# in mind that ls -t prints the *newest* file first.
rm -f conftest.ts?
: > conftest.ts1
: > conftest.ts2
: > conftest.ts3
# Make sure ls -t actually works. Do 'set' in a subshell so we don't
# clobber the current shell's arguments. (Outer-level square brackets
# are removed by m4; they're present so that m4 does not expand
# <dollar><star>; be careful, easy to get confused.)
if (
set X `[ls -t conftest.ts[12]]` &&
{
test "$[]*" != "X conftest.ts1 conftest.ts2" ||
test "$[]*" != "X conftest.ts2 conftest.ts1";
}
); then :; else
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
_AS_ECHO_UNQUOTED(
["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""],
[AS_MESSAGE_LOG_FD])
AC_MSG_FAILURE([ls -t produces unexpected output.
Make sure there is not a broken ls alias in your environment.])
fi
for am_try_res in $am_try_resolutions; do
# Any one fine-grained sleep might happen to cross the boundary
# between two values of a coarser actual resolution, but if we do
# two fine-grained sleeps in a row, at least one of them will fall
# entirely within a coarse interval.
echo alpha > conftest.ts1
sleep $am_try_res
echo beta > conftest.ts2
sleep $am_try_res
echo gamma > conftest.ts3
# We assume that 'ls -t' will make use of high-resolution
# timestamps if the operating system supports them at all.
if (set X `ls -t conftest.ts?` &&
test "$[]2" = conftest.ts3 &&
test "$[]3" = conftest.ts2 &&
test "$[]4" = conftest.ts1); then
#
# Ok, ls -t worked. If we're at a resolution of 1 second, we're done,
# because we don't need to test make.
make_ok=true
if test $am_try_res != 1; then
# But if we've succeeded so far with a subsecond resolution, we
# have one more thing to check: make. It can happen that
# everything else supports the subsecond mtimes, but make doesn't;
# notably on macOS, which ships make 3.81 from 2006 (the last one
# released under GPLv2). https://bugs.gnu.org/68808
#
# We test $MAKE if it is defined in the environment, else "make".
# It might get overridden later, but our hope is that in practice
# it does not matter: it is the system "make" which is (by far)
# the most likely to be broken, whereas if the user overrides it,
# probably they did so with a better, or at least not worse, make.
# https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html
#
# Create a Makefile (real tab character here):
rm -f conftest.mk
echo 'conftest.ts1: conftest.ts2' >conftest.mk
echo ' touch conftest.ts2' >>conftest.mk
#
# Now, running
# touch conftest.ts1; touch conftest.ts2; make
# should touch ts1 because ts2 is newer. This could happen by luck,
# but most often, it will fail if make's support is insufficient. So
# test for several consecutive successes.
#
# (We reuse conftest.ts[12] because we still want to modify existing
# files, not create new ones, per above.)
n=0
make=${MAKE-make}
until test $n -eq 3; do
echo one > conftest.ts1
sleep $am_try_res
echo two > conftest.ts2 # ts2 should now be newer than ts1
if $make -f conftest.mk | grep 'up to date' >/dev/null; then
make_ok=false
break # out of $n loop
fi
n=`expr $n + 1`
done
fi
#
if $make_ok; then
# Everything we know to check worked out, so call this resolution good.
am_cv_filesystem_timestamp_resolution=$am_try_res
break # out of $am_try_res loop
fi
# Otherwise, we'll go on to check the next resolution.
fi
done
rm -f conftest.ts?
# (end _am_filesystem_timestamp_resolution)
])])
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_REQUIRE([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION])
# This check should not be cached, as it may vary across builds of
# different projects.
AC_MSG_CHECKING([whether build environment is sane])
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[[\\\"\#\$\&\'\`$am_lf]]*)
AC_MSG_ERROR([unsafe absolute working directory name]);;
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
esac
# Do 'set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
am_build_env_is_sane=no
am_has_slept=no
rm -f conftest.file
for am_try in 1 2; do
echo "timestamp, slept: $am_has_slept" > conftest.file
if (
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$[]*" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
test "$[]2" = conftest.file
); then
am_build_env_is_sane=yes
break
fi
# Just in case.
sleep "$am_cv_filesystem_timestamp_resolution"
am_has_slept=yes
done
AC_MSG_RESULT([$am_build_env_is_sane])
if test "$am_build_env_is_sane" = no; then
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
# If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer.
am_sleep_pid=
AS_IF([test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1],, [dnl
( sleep "$am_cv_filesystem_timestamp_resolution" ) &
am_sleep_pid=$!
])
AC_CONFIG_COMMANDS_PRE(
[AC_MSG_CHECKING([that generated files are newer than configure])
if test -n "$am_sleep_pid"; then
# Hide warnings about reused PIDs.
wait $am_sleep_pid 2>/dev/null
fi
AC_MSG_RESULT([done])])
rm -f conftest.file
])
# Copyright (C) 2009-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_SILENT_RULES
# ----------------
# Enable less verbose build rules support.
AC_DEFUN([_AM_SILENT_RULES],
[AM_DEFAULT_VERBOSITY=1
AC_ARG_ENABLE([silent-rules], [dnl
AS_HELP_STRING(
[--enable-silent-rules],
[less verbose build output (undo: "make V=1")])
AS_HELP_STRING(
[--disable-silent-rules],
[verbose build output (undo: "make V=0")])dnl
])
dnl
dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
dnl do not support nested variable expansions.
dnl See automake bug#9928 and bug#10237.
am_make=${MAKE-make}
AC_CACHE_CHECK([whether $am_make supports nested variables],
[am_cv_make_support_nested_variables],
[if AS_ECHO([['TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi])
AC_SUBST([AM_V])dnl
AM_SUBST_NOTMAKE([AM_V])dnl
AC_SUBST([AM_DEFAULT_V])dnl
AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
AM_BACKSLASH='\'
AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
dnl Delay evaluation of AM_DEFAULT_VERBOSITY to the end to allow multiple calls
dnl to AM_SILENT_RULES to change the default value.
AC_CONFIG_COMMANDS_PRE([dnl
case $enable_silent_rules in @%:@ (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
esac
if test $am_cv_make_support_nested_variables = yes; then
dnl Using '$V' instead of '$(V)' breaks IRIX make.
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
])dnl
])
# AM_SILENT_RULES([DEFAULT])
# --------------------------
# Set the default verbosity level to DEFAULT ("yes" being less verbose, "no" or
# empty being verbose).
AC_DEFUN([AM_SILENT_RULES],
[AC_REQUIRE([_AM_SILENT_RULES])
AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1])])
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor 'install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
# always use install-sh in "make install-strip", and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
# Installed binaries are usually stripped using 'strip' when the user
# run "make install-strip". However 'strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the 'STRIP' environment variable to overrule this program.
dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
# --------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
# FORMAT should be one of 'v7', 'ustar', or 'pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
# $tardir.
# tardir=directory && $(am__tar) > result.tar
#
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
#
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AC_SUBST([AMTAR], ['$${TAR-tar}'])
# We'll loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
m4_if([$1], [v7],
[am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
[m4_case([$1],
[ustar],
[# The POSIX 1988 'ustar' format is defined with fixed-size fields.
# There is notably a 21 bits limit for the UID and the GID. In fact,
# the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
# and bug#13588).
am_max_uid=2097151 # 2^21 - 1
am_max_gid=$am_max_uid
# The $UID and $GID variables are not portable, so we need to resort
# to the POSIX-mandated id(1) utility. Errors in the 'id' calls
# below are definitely unexpected, so allow the users to see them
# (that is, avoid stderr redirection).
am_uid=`id -u || echo unknown`
am_gid=`id -g || echo unknown`
AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
if test x$am_uid = xunknown; then
AC_MSG_WARN([ancient id detected; assuming current UID is ok, but dist-ustar might not work])
elif test $am_uid -le $am_max_uid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi
AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
if test x$gm_gid = xunknown; then
AC_MSG_WARN([ancient id detected; assuming current GID is ok, but dist-ustar might not work])
elif test $am_gid -le $am_max_gid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi],
[pax],
[],
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Go ahead even if we have the value already cached. We do so because we
# need to set the values for the 'am__tar' and 'am__untar' variables.
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
for _am_tool in $_am_tools; do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar; do
AM_RUN_LOG([$_am_tar --version]) && break
done
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x $1 -w "$$tardir"'
am__tar_='pax -L -x $1 -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
am__untar='cpio -i -H $1 -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_$1}" && break
# tar/untar a dummy directory, and stop if the command works.
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
rm -rf conftest.dir
if test -s conftest.tar; then
AM_RUN_LOG([$am__untar <conftest.tar])
AM_RUN_LOG([cat conftest.dir/file])
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
# Copyright (C) 2022-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_PROG_XARGS_N
# ----------------
# Check whether 'xargs -n' works. It should work everywhere, so the fallback
# is not optimized at all as we never expect to use it.
AC_DEFUN([_AM_PROG_XARGS_N],
[AC_CACHE_CHECK([xargs -n works], am_cv_xargs_n_works, [dnl
AS_IF([test "`echo 1 2 3 | xargs -n2 echo`" = "1 2
3"], [am_cv_xargs_n_works=yes], [am_cv_xargs_n_works=no])])
AS_IF([test "$am_cv_xargs_n_works" = yes], [am__xargs_n='xargs -n'], [dnl
am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "$@" "$am__xargs_n_arg"; done; }'
])dnl
AC_SUBST(am__xargs_n)
])
+159
View File
@@ -0,0 +1,159 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package config
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"mproxy/pkg/auxx509"
yaml "go.yaml.in/yaml/v4"
)
type Service struct {
Address string `json:"address" yaml:"address"`
Port uint32 `json:"port" yaml:"port"`
}
type Database struct {
Basepath string `json:"basepath" yaml:"basepath"`
}
type Storage struct {
Basepath string `json:"basepath" yaml:"basepath"`
}
type Config struct {
Service Service `json:"service" yaml:"service"`
Database Database `json:"database" yaml:"database"`
Storage Storage `json:"storage" yaml:"storage"`
AsDaemon bool `json:"asDaemon" yaml:"asDaemon"`
Logpath string `json:"logpath" yaml:"logpath"`
Runpath string `json:"runpath" yaml:"runpath"`
Version string `json:"version" yaml:"version"`
Certpath string `json:"certpath,omitempty" yaml:"certpath,omitempty"`
Keypath string `json:"keypath,omitempty" yaml:"keypath,omitempty"`
X509Cert string `json:"-" yaml:"-"`
X509Key string `json:"-" yaml:"-"`
Datadir string `json:"datadir" yaml:"datadir"`
Hostname string `json:"hostname" yaml:"hostname"`
Hostnames []string `json:"hostnames" yaml:"hostnames"`
LogLimit int64 `json:"logLimit" yaml:"logLimit"`
RunUser string `json:"runUser" yaml:"runUser"`
}
func NewConfig() *Config {
logfile := fmt.Sprintf("%s.log", srvname)
logpath := filepath.Join(logdir, logfile)
runfile := fmt.Sprintf("%s.pid", srvname)
runpath := filepath.Join(rundir, runfile)
//certpath := fmt.Sprintf("%s.crt", srvname)
//certpath = filepath.Join(confdir, certpath)
//keypath := fmt.Sprintf("%s.crt", srvname)
//keypath = filepath.Join(confdir, keypath)
return &Config{
Service: Service{
Address: "0.0.0.0",
Port: 1025,
},
Database: Database{
Basepath: datadir,
},
Storage: Storage{
Basepath: datadir,
},
AsDaemon: false,
Logpath: logpath,
Runpath: runpath,
Version: version,
Datadir: datadir,
//Certpath: certpath,
//Keypath: keypath,
Hostnames: make([]string, 0),
LogLimit: 1024 * 1024 * 10, // 10 Mb
RunUser: "daemon",
}
}
func (conf *Config) String() string {
confbytes, _ := yaml.Marshal(conf)
return string(confbytes)
}
func (conf *Config) ReadConfigfile() error {
conffile := fmt.Sprintf("%s.yaml", srvname)
confpath := filepath.Join(confdir, conffile)
confdata, err := ioutil.ReadFile(confpath)
if err != nil {
return err
}
err = yaml.Unmarshal(confdata, conf)
if err != nil {
return err
}
return err
}
func (conf *Config) ReadX509Cert() error {
var err error
if conf.Certpath != "" && conf.Keypath != "" {
if !filepath.IsAbs(conf.Certpath) {
conf.Certpath = filepath.Join(confdir, conf.Certpath)
}
certBytes, err := os.ReadFile(conf.Certpath)
if err != nil {
return err
}
if !filepath.IsAbs(conf.Keypath) {
conf.Keypath = filepath.Join(confdir, conf.Keypath)
}
keyBytes, err := os.ReadFile(conf.Keypath)
if err != nil {
return err
}
conf.X509Cert = string(certBytes)
conf.X509Key = string(keyBytes)
return err
}
/*
if conf.X509Cert != "" && conf.X509Key != "" {
x509Cert, err := base64.StdEncoding.DecodeString(conf.X509Cert)
if err != nil {
return err
}
conf.X509Cert = string(x509Cert)
x509Key, err := base64.StdEncoding.DecodeString(conf.X509Key)
if err != nil {
return err
}
conf.X509Key = string(x509Key)
}
*/
if conf.X509Cert == "" || conf.X509Key == "" {
if conf.Hostname == "" {
conf.Hostname, err = os.Hostname()
if err != nil {
return err
}
}
certBytes, keyBytes, err := auxx509.CreateSelfSignedCert(conf.Hostname, conf.Hostnames...)
if err != nil {
return err
}
conf.X509Cert = string(certBytes)
conf.X509Key = string(keyBytes)
return err
}
return err
}
+10
View File
@@ -0,0 +1,10 @@
package config
const (
confdir = "@srv_confdir@"
rundir = "@srv_rundir@"
logdir = "@srv_logdir@"
datadir = "@srv_datadir@"
version = "@PACKAGE_VERSION@"
srvname = "@PACKAGE_NAME@d"
)
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package handler
import (
"context"
"fmt"
"mproxy/app/router"
"mproxy/pkg/auxhttp"
)
const (
authTag = "authpass"
userTag = "accountID"
)
func (hand *Handler) AuthMiddleware(next router.Handler) router.Handler {
var handlerFunc router.HandlerFunc
handlerFunc = func(rctx *router.Context) {
success, err := hand.CheckAccess(rctx)
if success {
rctx.SetBool(authTag, true)
}
if err != nil {
hand.logg.Errorf("Authorization middleware error: %v", err)
}
next.ServeHTTP(rctx)
}
return handlerFunc
}
// Authentification
func (hand *Handler) CheckAccess(rctx *router.Context) (bool, error) {
var err error
var success bool
var username string
var password string
authHeader := rctx.GetHeader("Proxy-Authorization")
hand.logg.Debugf("Proxy-Authorization: [%s]", authHeader)
if authHeader != "" {
username, password, err = auxhttp.ParseBasicAuth(authHeader)
if err != nil {
return success, err
}
success, err := hand.ValidatePassword(rctx.Ctx, username, password)
if err != nil {
return false, err
}
if !success {
err = fmt.Errorf("Incorrect username or password")
return false, err
}
return success, err
}
return success, err
}
func (hand *Handler) ValidatePassword(ctx context.Context, username, password string) (bool, error) {
var err error
valid := true
return valid, err
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package handler
import (
"net/http"
"mproxy/app/proxoper"
"mproxy/app/router"
)
func (hand *Handler) ConnectTo(rctx *router.Context) {
hostaddr, _ := rctx.GetSubpath("hostaddr")
params := &proxoper.ConnectToParams{
Hostaddr: hostaddr,
}
ctx := rctx.GetContext()
_, err := hand.prop.ConnectTo(ctx, params)
if err != nil {
hand.logg.Errorf("ConnectTo error: %v", err)
rctx.SetStatus(http.StatusInternalServerError)
return
}
rctx.SetStatus(http.StatusOK)
return
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package handler
import (
"mproxy/app/logger"
"mproxy/app/router"
"mproxy/app/proxoper"
"mproxy/app/servoper"
yaml "go.yaml.in/yaml/v4"
)
type HandlerParams struct {
ServOper *servoper.Operator
ProxOper *proxoper.Operator
}
type Handler struct {
logg *logger.Logger
seop *servoper.Operator
prop *proxoper.Operator
}
func NewHandler(params *HandlerParams) (*Handler, error) {
var err error
hand := &Handler{
seop: params.ServOper,
prop: params.ProxOper,
}
hand.logg = logger.NewLoggerWithSubject("handler")
return hand, err
}
func (hand *Handler) DumpHeaders(label string, rctx *router.Context) {
headers := rctx.GetHeaders()
yamlData, _ := yaml.Marshal(headers)
hand.logg.Debugf("%s:\n%s\n", label, string(yamlData))
}
+15
View File
@@ -0,0 +1,15 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package handler
import (
"net/http"
"mproxy/app/router"
)
func (hand *Handler) NotFound(rctx *router.Context) {
hand.logg.Warningf("Route for [%s %s] not found", rctx.Request.Method, rctx.Request.URL.String())
rctx.SetStatus(http.StatusNotFound)
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package handler
import (
"net/http"
"mproxy/app/router"
)
type Response[T any] struct {
Error bool `json:"error" yaml:"error"`
Message string `json:"message,omitempty" yaml:"message,omitempty"`
Result T `json:"result,omitempty" yaml:"result,result"`
}
func NewResponse[T any]() *Response[T] {
return &Response[T]{}
}
func (hand *Handler) SendResult(rctx *router.Context, result any) {
response := &Response[any]{
Error: false,
Result: result,
}
rctx.SendJSON(http.StatusOK, response)
}
func (hand *Handler) SendError(rctx *router.Context, err error) {
response := &Response[any]{
Error: true,
Message: err.Error(),
}
rctx.SendJSON(http.StatusOK, response)
}
+15
View File
@@ -0,0 +1,15 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package handler
import (
"mproxy/app/router"
"mproxy/app/servoper"
)
func (hand *Handler) SendHello(rctx *router.Context) {
params := &servoper.SendHelloParams{}
res, _ := hand.seop.SendHello(params)
hand.SendResult(rctx, res)
}
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package logger
import (
"bytes"
"fmt"
"io"
"os"
"sync"
"time"
)
var (
mtx sync.Mutex
output io.WriteCloser = os.Stderr
)
type Logger struct {
subject string
writer io.WriteCloser
mtx *sync.Mutex
}
func NewLoggerWithSubject(subj string) *Logger {
return &Logger{
subject: subj,
writer: output,
mtx: &mtx,
}
}
func NewLogger() *Logger {
return &Logger{
writer: output,
mtx: &mtx,
}
}
func SetWriter(newOut io.WriteCloser) {
mtx.Lock()
output = newOut
mtx.Unlock()
}
func (logg *Logger) SetWriter(newOut io.WriteCloser) {
mtx.Lock()
logg.writer = newOut
var newMtx sync.Mutex
logg.mtx = &newMtx
mtx.Unlock()
}
func (logg *Logger) Debugf(message string, args ...any) {
logg.printf("debug", message, args...)
}
func (logg *Logger) Infof(message string, args ...any) {
logg.printf("info", message, args...)
}
func (logg *Logger) Warningf(message string, args ...any) {
logg.printf("warning", message, args...)
}
func (logg *Logger) Errorf(message string, args ...any) {
logg.printf("error", message, args...)
}
func (logg *Logger) printf(level, message string, args ...any) {
timestamp := time.Now().Format(time.RFC3339)
buffer := bytes.NewBuffer([]byte{})
if logg.subject != "" {
fmt.Fprintf(buffer, "%s %s.%s: ", timestamp, logg.subject, level)
} else {
fmt.Fprintf(buffer, "%s %s: ", timestamp, level)
}
fmt.Fprintf(buffer, message, args...)
fmt.Fprintf(buffer, "\n")
logg.mtx.Lock()
fmt.Fprint(output, buffer.String())
logg.mtx.Unlock()
}
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package logger
import (
"io/ioutil"
"testing"
)
func TestLogger(t *testing.T) {
logg := NewLogger("test")
logg.Debugf("foo: %s", "bar")
}
func BenchmarkLoggerL(b *testing.B) {
SetWriter(ioutil.Discard)
logg := NewLogger("test")
for i := 0; i < b.N; i++ {
logg.Debugf("foo: %s", "bar")
}
}
func BenchmarkLoggerP(b *testing.B) {
SetWriter(ioutil.Discard)
logg := NewLogger("test")
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logg.Debugf("foo: %s", "bar")
}
})
}
+23
View File
@@ -0,0 +1,23 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package proxoper
import (
"context"
"io"
)
type ConnectToParams struct {
Hostaddr string
}
type ConnectToResult struct {
Stream io.Writer
}
func (oper *Operator) ConnectTo(ctx context.Context, param *ConnectToParams) (*ConnectToResult, error) {
var err error
res := &ConnectToResult{}
return res, err
}
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package proxoper
import (
"mproxy/app/logger"
)
type OperatorParams struct{}
type Operator struct {
logg *logger.Logger
}
func NewOperator(params *OperatorParams) (*Operator, error) {
var err error
oper := &Operator{}
oper.logg = logger.NewLoggerWithSubject("proxoper")
return oper, err
}
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
import (
"reflect"
"strconv"
)
// The code reflect string-string map to taged structure
// Limited, used only base types
// Don't ask me how it works. I'm only writer ;)
func bindObj(obj interface{}, kvmap map[string]string, sTag string) error {
var err error
vElem := reflect.ValueOf(obj).Elem()
sElem := reflect.TypeOf(obj).Elem()
for i := 0; i < vElem.NumField(); i++ {
vField := vElem.Field(i)
tag := sElem.Field(i).Tag.Get(sTag)
if tag != "" {
sVal, exists := kvmap[tag]
if exists {
switch vField.Kind() {
case reflect.String:
vField.SetString(sVal)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
iVal, err := strconv.ParseInt(sVal, 10, 64)
if err != nil {
return err
}
vField.SetInt(iVal)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
iVal, err := strconv.ParseUint(sVal, 10, 64)
if err != nil {
return err
}
vField.SetUint(iVal)
case reflect.Bool:
bVal, err := strconv.ParseBool(sVal)
if err != nil {
return err
}
vField.SetBool(bVal)
case reflect.Float32, reflect.Float64:
fVal, err := strconv.ParseFloat(sVal, 64)
if err != nil {
return err
}
vField.SetFloat(fVal)
}
}
}
}
return err
}
+150
View File
@@ -0,0 +1,150 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"net/url"
"strconv"
)
type Context struct {
Ctx context.Context
Request *http.Request
Writer http.ResponseWriter
PathMap map[string]string
Bools map[string]bool
Strings map[string]string
StatusCode int
}
func NewContext(writer http.ResponseWriter, request *http.Request) *Context {
rctx := &Context{
Writer: writer,
Request: request,
Ctx: request.Context(),
PathMap: make(map[string]string),
Bools: make(map[string]bool),
Strings: make(map[string]string),
}
return rctx
}
// Aux maps
func (rctx *Context) SetBool(key string, value bool) {
rctx.Bools[key] = value
}
func (rctx *Context) GetBool(key string) (bool, bool) {
exists, value := rctx.Bools[key]
return exists, value
}
func (rctx *Context) SetString(key string, value string) {
rctx.Strings[key] = value
}
func (rctx *Context) GetString(key string) (string, bool) {
value, exists := rctx.Strings[key]
return value, exists
}
// Request
func (rctx *Context) GetSubpath(key string) (string, bool) {
value, exists := rctx.PathMap[key]
return value, exists
}
func (rctx *Context) URL() *url.URL {
return rctx.Request.URL
}
func (rctx *Context) GetQuery(key string) string {
return rctx.Request.URL.Query().Get(key)
}
func (rctx *Context) GetHeader(key string) string {
return rctx.Request.Header.Get(key)
}
func (rctx *Context) GetHeaders() http.Header {
return rctx.Request.Header
}
func (rctx *Context) GetContext() context.Context {
return rctx.Request.Context()
}
// Binding
const emptyJSON = "{}"
func (rctx *Context) BindJSON(obj any) error {
buffer := bytes.NewBuffer(nil)
_, err := io.Copy(buffer, rctx.Request.Body)
if err != nil {
return err
}
reqBody := buffer.Bytes()
if len(reqBody) == 0 {
reqBody = []byte(emptyJSON)
}
err = json.Unmarshal(reqBody, obj)
if err != nil {
return err
}
return err
}
func (rctx *Context) BindQuery(obj any) error {
qMap := make(map[string]string)
for key, val := range rctx.Request.URL.Query() {
if len(val) == 1 {
qMap[key] = val[0]
}
}
return bindObj(obj, qMap, "param")
}
// Response
func (rctx *Context) SetHeader(key, value string) {
rctx.Writer.Header().Set(key, value)
}
func (rctx *Context) SetStatus(httpStatus int) {
rctx.StatusCode = httpStatus
rctx.Writer.WriteHeader(httpStatus)
}
func (rctx *Context) SendJSON(statusCode int, payload any) {
rctx.StatusCode = statusCode
buffer := bytes.NewBuffer(nil)
json.NewEncoder(buffer).Encode(payload)
rctx.Writer.Header().Set("Content-Type", "application/json")
size := strconv.FormatInt(int64(len(buffer.Bytes())), 10)
rctx.Writer.Header().Set("Content-Length", size)
rctx.Writer.WriteHeader(statusCode)
rctx.Writer.Write(buffer.Bytes())
}
func (rctx *Context) SendText(statusCode int, payload string) {
rctx.StatusCode = statusCode
size := strconv.FormatInt(int64(len(payload)), 10)
rctx.Writer.Header().Set("Content-Type", "text/plain")
rctx.Writer.Header().Set("Content-Length", size)
rctx.Writer.WriteHeader(statusCode)
rctx.Writer.Write([]byte(payload))
}
func (rctx *Context) SendBytes(statusCode int, ctype string, payload []byte) {
rctx.StatusCode = statusCode
size := strconv.FormatInt(int64(len(payload)), 10)
rctx.Writer.Header().Set("Content-Type", ctype)
rctx.Writer.Header().Set("Content-Length", size)
rctx.Writer.WriteHeader(statusCode)
rctx.Writer.Write(payload)
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
func NewCorsMiddleware() MiddlewareFunc {
mw := func(next Handler) Handler {
return newCorsHandler(next)
}
return mw
}
type corsHandler struct {
next Handler
}
func newCorsHandler(next Handler) *corsHandler {
return &corsHandler{
next: next,
}
}
func (hand corsHandler) ServeHTTP(ctx *Context) {
origin := ctx.Request.Header.Get("Origin")
if origin != "" {
ctx.SetHeader("Access-Control-Allow-Origin", origin)
ctx.SetHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE, PATCH")
ctx.SetHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
ctx.SetHeader("Access-Control-Max-Age", "86400")
ctx.SetHeader("Access-Control-Allow-Credentials", "true")
}
if ctx.Request.Method == "OPTIONS" {
return
}
hand.next.ServeHTTP(ctx)
}
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
func NewLoggingMiddleware(print func(string, ...any)) MiddlewareFunc {
mw := func(next Handler) Handler {
return newLoggingHandler(next, print)
}
return mw
}
type loggingHandler struct {
next Handler
printFunc func(string, ...any)
}
func newLoggingHandler(next Handler, print func(string, ...any)) *loggingHandler {
return &loggingHandler{
next: next,
printFunc: print,
}
}
func (logging loggingHandler) ServeHTTP(rctx *Context) {
logging.next.ServeHTTP(rctx)
cl := rctx.Writer.Header().Get("Content-Length")
logging.printFunc("%s %s %s %s %s %d", rctx.Request.RemoteAddr,
rctx.Request.Method, rctx.Request.URL.String(),
rctx.Request.Proto, cl, rctx.StatusCode)
}
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
import (
"fmt"
"strings"
)
const (
compContextPlain int = iota
compContextRegex
startRegex byte = '{'
stopRegex byte = '}'
defaultRegexp = `[a-zA-Z0-9_\.]+`
)
func pathCompiler(path string) (string, error) {
var err error
res := make([]byte, 0)
var pos int = compContextPlain
var depth int = 0
pattern := make([]byte, 0)
for _, b := range []byte(path) {
switch pos {
case compContextPlain:
switch b {
case stopRegex:
depth -= 1
res = append(res, b)
case startRegex:
depth += 1
pos = compContextRegex // pattern started
pattern = make([]byte, 0)
default:
res = append(res, b)
}
case compContextRegex:
switch b {
case startRegex:
depth += 1
case stopRegex:
depth -= 1
if depth == 0 {
pattern = convertRegexp(pattern)
res = append(res, pattern...)
pos = compContextPlain // pattern ended
}
default:
pattern = append(pattern, b)
}
}
}
if depth != 0 {
err = fmt.Errorf("Unbalanced brackets into pattern")
}
return string(res), err
}
func convertRegexp(src []byte) []byte {
var res string
const patternSeps = ":"
parts := strings.SplitN(string(src), patternSeps, 2)
if len(parts) == 1 {
parts = append(parts, defaultRegexp)
}
res = fmt.Sprintf("(?<%s>%s)", parts[0], parts[1])
return []byte(res)
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
import (
"fmt"
"regexp"
"testing"
"github.com/stretchr/testify/require"
)
func tDebugf(msg string, args ...any) {
fmt.Printf("debug: ")
fmt.Printf(msg, args...)
fmt.Printf("\n")
}
func TestPatchCompilerA(t *testing.T) {
var err error
srcPath := `/v1/file/{collection:[a-zA-Z]+}/{name}`
reSource, err := pathCompiler(srcPath)
require.NoError(t, err)
tDebugf("re: %s\n", reSource)
re, err := regexp.Compile(reSource)
require.NoError(t, err)
reqPath := `/v1/file/foo/bare`
match := re.MatchString(reqPath)
require.True(t, match)
submatch := re.FindStringSubmatch(reqPath)
subnames := re.SubexpNames()
submap := make(map[string]string)
for i, val := range subnames {
tDebugf("subname: %d = %s", i, val)
}
for i, val := range submatch {
key := subnames[i]
if key != "" {
submap[key] = val
}
tDebugf("sub: %d = %s", i, val)
}
tDebugf("submap: %v", submap)
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
import (
"net/http"
"runtime/debug"
"time"
)
func NewRecoveryMiddleware(print func(string, ...any)) MiddlewareFunc {
mw := func(next Handler) Handler {
return newRecoveryHandler(next, print)
}
return mw
}
type recoveryHandler struct {
next Handler
print func(string, ...any)
}
func newRecoveryHandler(next Handler, print func(string, ...any)) *recoveryHandler {
return &recoveryHandler{
next: next,
print: print,
}
}
func (hand recoveryHandler) ServeHTTP(rctx *Context) {
exitFunc := func() {
err := recover()
if err != nil {
rctx.Writer.WriteHeader(http.StatusInternalServerError)
stack := string(debug.Stack())
timestamp := time.Now().Format(time.RFC3339)
hand.print("%s %v ; %s\n", timestamp, err, stack)
}
}
defer exitFunc()
hand.next.ServeHTTP(rctx)
}
+166
View File
@@ -0,0 +1,166 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
import (
"fmt"
"net/http"
"regexp"
)
type MiddlewareFunc func(next Handler) Handler
type Handler interface {
ServeHTTP(rctx *Context)
}
type HandlerFunc func(rctx *Context)
func (handlerFunc HandlerFunc) ServeHTTP(rctx *Context) {
handlerFunc(rctx)
}
type Router struct {
headHandler Handler
routeHandler *Selector
}
func NewRouter() *Router {
selector := NewSelector()
return &Router{
routeHandler: selector,
headHandler: selector,
}
}
func (rout *Router) Use(mwFunc MiddlewareFunc) {
rout.headHandler = mwFunc(rout.headHandler)
}
func (rout *Router) Selector() *Selector {
return rout.routeHandler
}
func (rout *Router) AddRoute(method, path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute(method, path, handlerFunc)
}
func (rout *Router) Head(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("HEAD", path, handlerFunc)
}
func (rout *Router) Get(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("GET", path, handlerFunc)
}
func (rout *Router) Post(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("POST", path, handlerFunc)
}
func (rout *Router) Put(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("PUT", path, handlerFunc)
}
func (rout *Router) Patch(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("PATCH", path, handlerFunc)
}
func (rout *Router) Delete(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("DELETE", path, handlerFunc)
}
func (rout *Router) Connect(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("CONNECT", path, handlerFunc)
}
func (rout *Router) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
rctx := NewContext(writer, req)
rout.headHandler.ServeHTTP(rctx)
}
func (rout *Router) NotFound(handlerFunc HandlerFunc) {
rout.routeHandler.notFound = handlerFunc
}
type Selector struct {
Routes []*Route
notFound Handler
}
func NewSelector() *Selector {
notFound := HandlerFunc(func(ctx *Context) {
http.NotFound(ctx.Writer, ctx.Request)
})
return &Selector{
Routes: make([]*Route, 0),
notFound: notFound,
}
}
const globalRoutePattern = `^%s$`
func (hand *Selector) AddRoute(method, path string, handlerFunc HandlerFunc) error {
var err error
rawPath := path
path, err = pathCompiler(path)
if err != nil {
return err
}
path = fmt.Sprintf(globalRoutePattern, path)
re, err := regexp.Compile(path)
if err != nil {
return err
}
route := &Route{
Method: method,
Path: path,
RawPath: rawPath,
Handler: handlerFunc,
Regexp: re,
}
hand.Routes = append(hand.Routes, route)
return err
}
func (hand *Selector) ServeHTTP(rctx *Context) {
realHandler := hand.notFound
for _, route := range hand.Routes {
match := route.Match(rctx.Request)
if !match {
continue
}
subvals := route.Regexp.FindStringSubmatch(rctx.Request.URL.Path)
subkeys := route.Regexp.SubexpNames()
for i, val := range subvals {
key := subkeys[i]
if key != "" {
rctx.PathMap[key] = val
}
}
realHandler = route.Handler
break
}
realHandler.ServeHTTP(rctx)
}
type Route struct {
Method string
Regexp *regexp.Regexp
Path string
RawPath string
Handler HandlerFunc
}
func (route Route) Match(req *http.Request) bool {
if req.Method != route.Method {
return false
}
match := route.Regexp.MatchString(req.URL.Path)
if match {
return true
}
return false
}
+195
View File
@@ -0,0 +1,195 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package router
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
)
func TestRouterStatus(t *testing.T) {
reqPath := "/hello"
handler := NewRouter()
helloHandler := func(rctx *Context) {
rctx.SetStatus(http.StatusOK)
}
handler.Get(reqPath, helloHandler)
request, err := http.NewRequest("GET", reqPath, nil)
require.NoError(t, err)
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
require.Equal(t, http.StatusOK, recorder.Code)
fmt.Printf("Response code: %d\n", recorder.Code)
}
func TestRouterSendText(t *testing.T) {
testText := "hello, world"
reqPath := "/hello"
rout := NewRouter()
helloHandler := func(rctx *Context) {
rctx.SendText(http.StatusOK, testText)
}
rout.Get(reqPath, helloHandler)
request, err := http.NewRequest("GET", reqPath, nil)
require.NoError(t, err)
recorder := httptest.NewRecorder()
rout.ServeHTTP(recorder, request)
fmt.Printf("Response code: %d\n", recorder.Code)
require.Equal(t, http.StatusOK, recorder.Code)
bodyReader := recorder.Body
bodyBytes, err := io.ReadAll(bodyReader)
fmt.Printf("Response body: %s\n", string(bodyBytes))
require.Equal(t, string(bodyBytes), testText)
}
func TestRouterSendJSON(t *testing.T) {
type testStruct struct {
Message string `json:"message"`
Code int64 `json:"code"`
}
testVar := testStruct{
Message: "hello, world",
Code: 123,
}
testData, err := json.Marshal(testVar)
require.NoError(t, err)
reqPath := "/hello"
handler := NewRouter()
helloHandler := func(rctx *Context) {
rctx.SendJSON(http.StatusOK, &testVar)
}
handler.Get(reqPath, helloHandler)
request, err := http.NewRequest("GET", reqPath, nil)
require.NoError(t, err)
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
fmt.Printf("Response code: %d\n", recorder.Code)
require.Equal(t, http.StatusOK, recorder.Code)
bodyReader := recorder.Body
bodyBytes, err := io.ReadAll(bodyReader)
require.NoError(t, err)
bodyBytes = bytes.Trim(bodyBytes, "\n\r")
fmt.Printf("Response body: %s\n", string(bodyBytes))
require.Equal(t, string(testData), string(bodyBytes))
}
func TestRouterBindJSON(t *testing.T) {
type testStruct struct {
Message string `json:"message"`
Code int64 `json:code"`
}
testVar := testStruct{
Message: "hello, world",
Code: 123,
}
testData, err := json.Marshal(testVar)
require.NoError(t, err)
buffer := bytes.NewBuffer(testData)
reqPath := "/hello"
handler := NewRouter()
helloHandler := func(rctx *Context) {
handVar := testStruct{}
rctx.BindJSON(&handVar)
fmt.Printf("Received message: %s - %d\n", handVar.Message, handVar.Code)
require.Equal(t, handVar.Code, int64(123))
rctx.SendJSON(http.StatusOK, &handVar)
}
handler.Post(reqPath, helloHandler)
request, err := http.NewRequest("POST", reqPath, buffer)
require.NoError(t, err)
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
fmt.Printf("Response code: %d\n", recorder.Code)
require.Equal(t, http.StatusOK, recorder.Code)
bodyReader := recorder.Body
bodyBytes, err := io.ReadAll(bodyReader)
require.NoError(t, err)
bodyBytes = bytes.Trim(bodyBytes, "\n\r")
fmt.Printf("Response body: %s\n", string(bodyBytes))
require.Equal(t, string(testData), string(bodyBytes))
}
func TestRouterBindParams(t *testing.T) {
reqPath := "/hello"
handler := NewRouter()
helloHandler := func(rctx *Context) {
type Params struct {
Name string `param:"name"`
Code int64 `param:"code"`
}
params := &Params{}
rctx.BindQuery(params)
fmt.Printf("Received name: %s\n", params.Name)
fmt.Printf("Received code: %d\n", params.Code)
rctx.SendText(http.StatusOK, "hello")
}
handler.Get(reqPath, helloHandler)
reqPath = reqPath + `?name=world&code=123`
request, err := http.NewRequest("GET", reqPath, nil)
require.NoError(t, err)
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
fmt.Printf("Response code: %d\n", recorder.Code)
require.Equal(t, http.StatusOK, recorder.Code)
bodyReader := recorder.Body
bodyBytes, err := io.ReadAll(bodyReader)
require.NoError(t, err)
bodyBytes = bytes.Trim(bodyBytes, "\n\r")
fmt.Printf("Response body: %s\n", string(bodyBytes))
}
func BenchmarkLoggerL(b *testing.B) {
reqPath := "/hello"
helloHandler := func(rctx *Context) {
rctx.SetStatus(http.StatusOK)
}
handler := NewRouter()
handler.Get(reqPath, helloHandler)
request, err := http.NewRequest("GET", reqPath, nil)
require.NoError(b, err)
for i := 0; i < b.N; i++ {
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
require.Equal(b, http.StatusOK, recorder.Code)
}
}
+418
View File
@@ -0,0 +1,418 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
*
*/
package server
import (
"context"
"fmt"
"net"
"os"
"os/signal"
"os/user"
"path/filepath"
"strconv"
"sync"
"syscall"
"time"
"mproxy/app/config"
"mproxy/app/handler"
"mproxy/app/logger"
"mproxy/app/service"
"mproxy/pkg/auxtool"
"mproxy/app/proxoper"
"mproxy/app/servoper"
)
type Server struct {
conf *config.Config
seop *servoper.Operator
prop *proxoper.Operator
svc *service.Service
hand *handler.Handler
logg *logger.Logger
ctx context.Context
cancel context.CancelFunc
wg sync.WaitGroup
logf *os.File
//x509cert []byte
//x509key []byte
listen net.Listener
}
func NewServer() (*Server, error) {
var err error
srv := &Server{}
srv.logg = logger.NewLoggerWithSubject("server")
srv.ctx, srv.cancel = context.WithCancel(context.Background())
return srv, err
}
func (srv *Server) Handler() *handler.Handler {
return srv.hand
}
func (srv *Server) Service() *service.Service {
return srv.svc
}
func (srv *Server) SetLogdir(dir string) {
srv.conf.Logpath = dir
}
func (srv *Server) SetRundir(dir string) {
srv.conf.Runpath = dir
}
func (srv *Server) SetDatadir(dir string) {
srv.conf.Database.Basepath = dir
srv.conf.Storage.Basepath = dir
srv.conf.Datadir = dir
}
func (srv *Server) SetPort(port uint32) {
srv.conf.Service.Port = port
}
func (srv *Server) SetAsDaemon(asDaemon bool) {
srv.conf.AsDaemon = asDaemon
}
func (srv *Server) Configure() error {
var err error
//srv.logg.Infof("Configuration server")
srv.conf = config.NewConfig()
if err != nil {
return err
}
err = srv.conf.ReadConfigfile()
if err != nil {
srv.logg.Warningf("Error loading config file: %v", err)
err = nil
}
err = srv.conf.ReadX509Cert()
if err != nil {
return err
}
return err
}
func (srv *Server) Build() error {
var err error
//srv.logg.Infof("Server building")
currUser, err := user.Current()
if err != nil {
err = fmt.Errorf("Error getting current user: %v\n", err)
return err
}
cuid64, err := strconv.ParseInt(currUser.Uid, 10, 64)
if err != nil {
return err
}
cgid64, err := strconv.ParseInt(currUser.Gid, 10, 64)
if err != nil {
return err
}
euid := int(cuid64)
egid := int(cgid64)
if cuid64 == 0 {
usr, err := user.Lookup(srv.conf.RunUser)
if err != nil {
return err
}
uid64, err := strconv.ParseInt(usr.Uid, 10, 64)
if err != nil {
return err
}
gid64, err := strconv.ParseInt(usr.Gid, 10, 64)
if err != nil {
return err
}
euid = int(uid64)
egid = int(gid64)
}
// Creating datadir
datadir := srv.conf.Datadir
if !auxtool.DirExists(datadir) { // TODO: check access to dir
//srv.logg.Infof("Creating data directory %s ", datadir)
err = os.MkdirAll(datadir, 0750)
if err != nil {
return err
}
}
err = os.Chown(datadir, euid, egid)
if err != nil {
return err
}
if srv.conf.AsDaemon {
logdir := filepath.Dir(srv.conf.Logpath)
//srv.logg.Infof("Creating log directory %s", logdir)
err = os.MkdirAll(logdir, 0750)
if err != nil {
return err
}
err = os.Chown(logdir, euid, egid)
if err != nil {
return err
}
rundir := filepath.Dir(srv.conf.Runpath)
//srv.logg.Infof("Creating run directory %s", rundir)
err = os.MkdirAll(rundir, 0750)
if err != nil {
return err
}
err = os.Chown(rundir, euid, egid)
if err != nil {
return err
}
// Redirect stderr and stout
logFile, err := os.OpenFile(srv.conf.Logpath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
if err != nil {
return err
}
err = syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd()))
if err != nil {
return err
}
err = syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
if err != nil {
return err
}
srv.logf = logFile
}
confDump := srv.conf.String()
srv.logg.Infof("Current server configuration is:\n%s\n", confDump)
if cuid64 == 0 {
// Change effective user and group
err = syscall.Setgid(egid)
if err != nil {
return err
}
err = syscall.Setuid(euid)
if err != nil {
return err
}
}
//return fmt.Errorf("Debug break")
uidstr := strconv.FormatInt(int64(syscall.Geteuid()), 10)
usr, err := user.LookupId(uidstr)
if err != nil {
return err
}
srv.logg.Warningf("Now run as user: %s", usr.Username)
// Creating service operator
srv.logg.Infof("Creating operator")
servoperParams := &servoper.OperatorParams{}
srv.seop, err = servoper.NewOperator(servoperParams)
if err != nil {
return err
}
// Creating proxy operator
srv.logg.Infof("Creating operator")
proxoperParams := &proxoper.OperatorParams{}
srv.prop, err = proxoper.NewOperator(proxoperParams)
if err != nil {
return err
}
// Creating handler
srv.logg.Infof("Creating handler")
handlerParams := &handler.HandlerParams{
ServOper: srv.seop,
ProxOper: srv.prop,
}
srv.hand, err = handler.NewHandler(handlerParams)
if err != nil {
return err
}
// Creating service
serviceParams := &service.ServiceParams{
Handler: srv.hand,
X509cert: srv.conf.X509Cert,
X509key: srv.conf.X509Key,
Address: srv.conf.Service.Address,
Portnum: srv.conf.Service.Port,
}
srv.logg.Infof("Creating service")
srv.svc, err = service.NewService(serviceParams)
if err != nil {
return err
}
// Building service
err = srv.svc.Build()
if err != nil {
return err
}
return err
}
func (srv *Server) Run() error {
var err error
if srv.conf.AsDaemon {
// Redirect stdin
nullFile, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
if err != nil {
return err
}
err = syscall.Dup2(int(nullFile.Fd()), int(os.Stdin.Fd()))
if err != nil {
return err
}
// Write process ID
pidFile, err := os.OpenFile(srv.conf.Runpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
if err != nil {
return err
}
defer pidFile.Close()
currPid := os.Getpid()
_, err = pidFile.WriteString(strconv.Itoa(currPid))
if err != nil {
return err
}
// Start log rotator
srv.Rotator()
}
currUser, err := user.Current()
if err != nil {
return err
}
srv.logg.Infof("Server started with user: %s", currUser.Username)
uidstr := strconv.FormatInt(int64(syscall.Geteuid()), 10)
usr, err := user.LookupId(uidstr)
if err != nil {
return err
}
srv.logg.Infof("Server run with user: %s", usr.Username)
svcDone := make(chan error, 1)
// Service run
srv.logg.Infof("Start service")
startService := func(svc *service.Service, done chan error) {
err = svc.Run()
if err != nil {
srv.logg.Errorf("Service error: %v", err)
done <- err
}
}
go startService(srv.svc, svcDone)
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
var signal os.Signal
select {
case signal = <-sigs:
srv.logg.Infof("Services stopped by signal: %v", signal)
srv.cancel()
srv.svc.Stop()
srv.wg.Wait()
case err = <-svcDone:
srv.logg.Infof("Service stopped by service error: %v", err)
srv.cancel()
srv.svc.Stop()
srv.wg.Wait()
}
return err
}
func (srv *Server) PseudoFork() error {
const successExit int = 0
var keyEnv string = "IMX0LTSELMRF8K"
var err error
_, isChild := os.LookupEnv(keyEnv)
switch {
case !isChild:
os.Setenv(keyEnv, "TRUE")
procAttr := syscall.ProcAttr{}
cwd, err := os.Getwd()
if err != nil {
return err
}
var sysFiles = make([]uintptr, 3)
sysFiles[0] = uintptr(syscall.Stdin)
sysFiles[1] = uintptr(syscall.Stdout)
sysFiles[2] = uintptr(syscall.Stderr)
procAttr.Files = sysFiles
procAttr.Env = os.Environ()
procAttr.Dir = cwd
_, err = syscall.ForkExec(os.Args[0], os.Args, &procAttr)
if err != nil {
return err
}
os.Exit(successExit)
case isChild:
_, err = syscall.Setsid()
if err != nil {
return err
}
}
os.Unsetenv(keyEnv)
return err
}
func (srv *Server) Daemonize() error {
var err error
if srv.conf.AsDaemon {
// Restart process process
err = srv.PseudoFork()
if err != nil {
return err
}
}
return err
}
func (srv *Server) Rotator() {
srv.wg.Add(1)
var counter uint64
logFunc := func() {
for {
counter += 1
select {
case <-srv.ctx.Done():
srv.wg.Done()
srv.logg.Infof("Log file rotator done")
return
default:
}
if (counter % 60) == 1 {
stat, err := srv.logf.Stat()
if err == nil && stat.Size() > srv.conf.LogLimit {
srv.logg.Infof("Rotate log file")
countFiles := 3
for i := 1; i < countFiles; i++ {
nextName := fmt.Sprintf("%s.%d", srv.conf.Logpath, i+1)
prevName := fmt.Sprintf("%s.%d", srv.conf.Logpath, i)
os.Rename(prevName, nextName)
}
os.Rename(srv.conf.Logpath, srv.conf.Logpath+".1")
logFile, err := os.OpenFile(srv.conf.Logpath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
if err == nil {
syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd()))
syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
srv.logf.Close()
srv.logf = logFile
}
}
}
time.Sleep(1 * time.Second)
}
}
go logFunc()
}
+136
View File
@@ -0,0 +1,136 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package service
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"time"
"mproxy/app/handler"
"mproxy/app/logger"
"mproxy/app/router"
)
type ServiceParams struct {
Handler *handler.Handler
Address string
Portnum uint32
X509cert string
X509key string
}
type Service struct {
hand *handler.Handler
rout *router.Router
logg *logger.Logger
hsrv *http.Server
address string
portnum uint32
listen net.Listener
x509cert string
x509key string
protocol string
}
func NewService(params *ServiceParams) (*Service, error) {
var err error
svc := &Service{
hand: params.Handler,
address: params.Address,
portnum: params.Portnum,
x509cert: params.X509cert,
x509key: params.X509key,
protocol: "TCP",
}
svc.logg = logger.NewLoggerWithSubject("service")
return svc, err
}
func (svc *Service) Build() error {
var err error
svc.logg.Infof("Service build ")
svc.rout = router.NewRouter()
svc.rout.Use(router.NewRecoveryMiddleware(svc.logg.Errorf))
svc.rout.Use(router.NewLoggingMiddleware(svc.logg.Infof))
svc.rout.Use(router.NewCorsMiddleware())
svc.rout.Use(svc.hand.AuthMiddleware)
svc.rout.Get(`/v3/api/service/hello`, svc.hand.SendHello)
svc.rout.Connect(`{hostaddr}`, svc.hand.ConnectTo)
svc.rout.NotFound(svc.hand.NotFound)
selector := svc.rout.Selector()
for _, item := range selector.Routes {
svc.logg.Infof("%s\t%s", item.Method, item.RawPath)
}
const useTLS = true
if useTLS {
tlsCert, err := tls.X509KeyPair([]byte(svc.x509cert), []byte(svc.x509key))
if err != nil {
return err
}
tlsConfig := tls.Config{
Certificates: []tls.Certificate{tlsCert},
ClientAuth: tls.NoClientCert,
InsecureSkipVerify: true,
}
listenAddress := fmt.Sprintf("%s:%d", svc.address, svc.portnum)
svc.listen, err = tls.Listen(svc.protocol, listenAddress, &tlsConfig)
if err != nil {
return err
}
} else {
listenAddress := fmt.Sprintf("%s:%d", svc.address, svc.portnum)
svc.listen, err = net.Listen(svc.protocol, listenAddress)
if err != nil {
return err
}
}
svc.logg.Infof("Service listening at %v", svc.listen.Addr())
svc.hsrv = &http.Server{
Handler: svc.rout,
}
return err
}
func (svc *Service) Run() error {
var err error
svc.logg.Infof("Service run")
err = svc.hsrv.Serve(svc.listen)
if err == http.ErrServerClosed {
svc.logg.Warningf("Service Closed")
err = nil
}
if err != nil {
return err
}
return err
}
func (svc *Service) Stop() {
if svc.hsrv != nil {
svc.logg.Infof("Service stop")
downWaiting := 10 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), downWaiting)
defer cancel()
err := svc.hsrv.Shutdown(ctx)
if err != nil {
svc.logg.Errorf("Error service shutdown: %v", err)
}
}
}
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package servoper
import (
"mproxy/app/logger"
)
type OperatorParams struct{}
type Operator struct {
logg *logger.Logger
}
func NewOperator(params *OperatorParams) (*Operator, error) {
var err error
oper := &Operator{}
oper.logg = logger.NewLoggerWithSubject("servoper")
return oper, err
}
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package servoper
type SendHelloParams struct{}
type SendHelloResult struct {
Message string `json:"message"`
Alive bool `json:"alive"`
}
func (oper *Operator) SendHello(param *SendHelloParams) (*SendHelloResult, error) {
var err error
res := &SendHelloResult{
Alive: true,
Message: "hello",
}
return res, err
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package main
import (
"mproxy/cmd/mproxyctl/util"
"os"
)
func main() {
var err error
util := util.NewUtil()
err = util.Build()
if err != nil {
os.Exit(1)
}
err = util.Exec(os.Args[1:])
if err != nil {
os.Exit(1)
}
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package util
import (
"fmt"
"os"
"path/filepath"
"github.com/spf13/cobra"
)
type Util struct {
rootCmd *cobra.Command
}
func NewUtil() *Util {
return &Util{}
}
func (util *Util) GetRooCmd() *cobra.Command {
return util.rootCmd
}
func (util *Util) Build() error {
var err error
execName := filepath.Base(os.Args[0])
rootCmd := &cobra.Command{
Use: execName,
Short: "\nOperation with artefacts: files, images, service accounts and grants",
SilenceUsage: true,
}
rootCmd.CompletionOptions.DisableDefaultCmd = true
util.rootCmd = rootCmd
return err
}
func (util *Util) Exec(args []string) error {
var err error
util.rootCmd.SetArgs(args)
err = util.rootCmd.Execute()
return err
}
func (util *Util) Hello(cmd *cobra.Command, args []string) {
fmt.Println("hello, world!")
}
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package main
import (
"os"
"mproxy/app/logger"
"mproxy/cmd/mproxyd/starter"
_ "mproxy/app/handler"
)
func main() {
log := logger.NewLoggerWithSubject("main")
sta := starter.NewStarter()
err := sta.Exec()
if err != nil {
log.Errorf("%v", err)
os.Exit(1)
}
os.Exit(0)
}
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package starter
import (
"os"
"path/filepath"
"mproxy/app/server"
"github.com/spf13/cobra"
)
type Starter struct {
runAsDaemon bool
port uint32
cmd *cobra.Command
srv *server.Server
}
func NewStarter() *Starter {
execName := filepath.Base(os.Args[0])
sta := &Starter{}
cmd := &cobra.Command{
Use: execName,
Short: "\nArtifact storage service",
SilenceUsage: true,
RunE: sta.run,
}
cmd.CompletionOptions.DisableDefaultCmd = true
cmd.Flags().BoolVarP(&sta.runAsDaemon, "asDaemon", "D", true, "Run service as daemon")
cmd.Flags().Uint32VarP(&sta.port, "port", "P", 1025, "Service port")
sta.cmd = cmd
return sta
}
func (sta *Starter) GetCmd() *cobra.Command {
return sta.cmd
}
func (sta *Starter) run(cmd *cobra.Command, args []string) error {
var err error
srv, err := server.NewServer()
if err != nil {
return err
}
err = srv.Configure()
if err != nil {
return err
}
srv.SetAsDaemon(sta.runAsDaemon)
srv.SetPort(sta.port)
err = srv.Daemonize()
if err != nil {
return err
}
err = srv.Build()
if err != nil {
return err
}
err = srv.Run()
if err != nil {
return err
}
sta.srv = srv
return err
}
func (sta *Starter) Exec() error {
return sta.cmd.Execute()
}
Vendored Executable
+1815
View File
File diff suppressed because it is too large Load Diff
Vendored Executable
+2354
View File
File diff suppressed because it is too large Load Diff
Vendored Executable
+5139
View File
File diff suppressed because it is too large Load Diff
+256
View File
@@ -0,0 +1,256 @@
AC_INIT([mproxy],[0.0.1])
AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax])
AC_PREFIX_DEFAULT(/usr/local)
PACKAGE=mproxy
AC_CHECK_PROG(HAVE_GO, go, true, false)
if test "x$HAVE_GO" = "xfalse"; then
AC_MSG_ERROR([Requested program go not found])
fi
AC_PATH_PROG([GO],[go])
AC_PATH_PROG([FIND],[find])
AC_PATH_PROG([XARGS],[xargs])
AC_PATH_PROG([SORT],[sort])
AC_PATH_PROG([UNIQ],[uniq])
AC_PATH_PROGS([SUDO],[sudo false])
AC_PATH_PROGS([CPIO],[cpio false])
AC_PATH_PROGS([BASENAME],[basename])
AC_PATH_PROGS([PODMAN],[podman true])
AC_PATH_PROGS([HELM],[helm true])
AC_PATH_PROGS([DBUILDPACKAGE],[dpkg-buildpackage true])
AC_PATH_PROGS([DPKGSOURCE],[dpkg-source true])
AC_PATH_PROGS([SWAG],[swag true])
AC_PATH_PROGS([CP],[gcp cp])
if test -z "$CP"; then
AC_MSG_ERROR([Requested program cp not found])
fi
AC_PROG_INSTALL
AC_PROG_MKDIR_P
AC_CANONICAL_HOST
case $host_os in
*freebsd* )
AC_SUBST(ROOT_GROUP, "wheel")
AM_CONDITIONAL(FREEBSD_OS, true)
AM_CONDITIONAL(LINUX_OS, false)
OSNAME=freebsd
ROOT_GROUP=wheel
;;
*linux* )
AC_SUBST(ROOT_GROUP, "root")
AM_CONDITIONAL(FREEBSD_OS, false)
AM_CONDITIONAL(LINUX_OS, true)
OSNAME=linux
ROOT_GROUP=root
;;
esac
AM_CONDITIONAL(SYSTEMD, false)
if test -d /lib/systemd/system; then
AM_CONDITIONAL(SYSTEMD, true)
fi
test "x$prefix" == "xNONE" && prefix=$ac_default_prefix
test "x$libexecdir" == "xNONE" && libexecdir=${prefix}/lib
dnl --------------------------------------------------------------------------------------
AC_ARG_ENABLE([devel-mode],
AS_HELP_STRING([--enable-devel-mode], [Enable developmend mode]))
AC_DEFINE_UNQUOTED(srv_devel_mode, "false", [developmend mode])
AC_SUBST(srv_devel_mode, "false")
AS_IF([test "x$enable_devel_mode" = "xyes"], [
SRCDIR=`pwd`
enable_devel_mode=yes
])
dnl --------------------------------------------------------------------------------------
SRV_CONFDIR="${prefix}/etc/${PACKAGE}"
AC_ARG_WITH(confdir,
AS_HELP_STRING([--with-confdir=PATH],[set configuration dir to PATH (default: $SRV_CONFDIR)]),
[ if test ! -z "$withval" ; then
case $withval in
/*)
SRV_CONFDIR="$withval"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-confdir=PATH)
;;
esac
fi ])
AS_IF([test "x$enable_devel_mode" = "xyes"], [
SRV_CONFDIR="${SRCDIR}/etc/${PACKAGE}"
sysconfdir="${SRCDIR}/etc/${PACKAGE}"
], [
test "x$SRV_CONFDIR" == "x/usr/etc/${PACKAGE}" && SRV_CONFDIR="/etc/${PACKAGE}"
test "x$prefix" == "x/usr" && sysconfdir="/etc"
])
AC_DEFINE_UNQUOTED(SRV_CONFDIR, "$SRV_CONFDIR", [location of configuration files for ${PACKAGE}])
AC_SUBST(srv_confdir, "$SRV_CONFDIR")
AC_MSG_NOTICE(srv_confdir set as ${SRV_CONFDIR})
dnl --------------------------------------------------------------------------------------
SRV_LOGDIR="/var/log/${PACKAGE}"
AC_ARG_WITH(logdir,
AS_HELP_STRING([--with-logdir=PATH],[set path for logdir (default: $SRV_LOGDIR)]),
[ if test ! -z "$withval" ; then
case $withval in
/*)
SRV_LOGDIR="$withval"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-logdir=PATH)
;;
esac
fi])
AS_IF([test "x$enable_devel_mode" = "xyes"], [
SRV_LOGDIR="${SRCDIR}/tmp/log"
])
AC_DEFINE_UNQUOTED(SRV_LOGDIR, "$SRV_LOGDIR", [location of ${PACKAGE} logdir])
AC_SUBST(srv_logdir, "$SRV_LOGDIR")
AC_MSG_NOTICE(srv_logdir set as ${SRV_LOGDIR})
dnl --------------------------------------------------------------------------------------
SRV_RUNDIR="/var/run/${PACKAGE}"
AC_ARG_WITH(rundir,
AS_HELP_STRING([--with-rundir=PATH],[set path for rundir (default: $SRV_RUNDIR)]),
[ if test ! -z "$withval" ; then
case $withval in
/*)
SRV_RUNDIR="$withval"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-rundir=PATH)
;;
esac
fi ])
AS_IF([test "x$enable_devel_mode" = "xyes"], [
SRV_RUNDIR="${SRCDIR}/tmp/run"
])
AC_DEFINE_UNQUOTED(SRV_RUNDIR, "$SRV_RUNDIR", [location of rundir])
AC_SUBST(srv_rundir, "$SRV_RUNDIR")
AC_MSG_NOTICE(srv_rundir set as ${SRV_RUNDIR})
dnl --------------------------------------------------------------------------------------
SRV_SHAREDIR="${prefix}/share/$PACKAGE"
AC_ARG_WITH(sharedir,
AS_HELP_STRING([--with-sharedir=PATH],[set share directory (default: $SRV_SHAREDIR)]),
[ if test ! -z "$with_sharedir" ; then
case $with_sharedir in
/*)
SRV_SHAREDIR="$withval"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-sharedir=PATH)
;;
esac
fi ])
AS_IF([test "x$enable_devel_mode" = "xyes"], [
SRV_SHAREDIR="${SRCDIR}/share"
])
AC_DEFINE_UNQUOTED(SRV_SHAREDIR, "$SRV_SHAREDIR", [location of share dir])
AC_SUBST(srv_sharedir, "$SRV_SHAREDIR")
AC_MSG_NOTICE(srv_sharedir set as ${SRV_SHAREDIR})
dnl --------------------------------------------------------------------------------------
SRV_LIBDIR="${prefix}/lib/$PACKAGE"
AC_ARG_WITH(libdir,
AS_HELP_STRING([--with-libdir=PATH],[set lib directory (default: $SRV_LIBDIR)]),
[ if test ! -z "$withval" ; then
case $withval in
/*)
SRV_LIBDIR="$withval"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-libdir=PATH)
;;
esac
fi ])
AS_IF([test "x$enable_devel_mode" = "xyes"], [
SRV_LIBDIR="${SRCDIR}/sysagent"
])
AC_DEFINE_UNQUOTED(SRV_LIBDIR, "$SRV_LIBDIR", [location of lib dir])
AC_SUBST(srv_libdir, "$SRV_LIBDIR")
AC_MSG_NOTICE(srv_libdir set as ${SRV_LIBDIR})
dnl --------------------------------------------------------------------------------------
SRV_DATADIR="/var/lib/${PACKAGE}"
AC_ARG_WITH(datadir,
AS_HELP_STRING([--with-datadir=PATH],[set path for datadir (default: $SRV_DATADIR)]),
[ if test ! -z "$withval" ; then
case $withval in
/*)
SRV_DATADIR="$withval"
;;
*)
AC_MSG_ERROR(You must specify an absolute path to --with-datadir=PATH)
;;
esac
fi])
AS_IF([test "x$enable_devel_mode" = "xyes"], [
SRV_DATADIR="${SRCDIR}/tmp/data"
])
AC_DEFINE_UNQUOTED(SRV_DATADIR, "$SRV_DATADIR", [location of ${PACKAGE} datadir])
AC_SUBST(srv_datadir, "$SRV_DATADIR")
AC_MSG_NOTICE(srv_datadir set as ${SRV_DATADIR})
dnl --------------------------------------------------------------------------------------
AM_EXTRA_RECURSIVE_TARGETS([docs])
AC_CONFIG_FILES([
Makefile
app/config/variant.go
initrc/mproxyd.service
initrc/mproxyd
debian/control
debian/changelog
mans/Makefile
])
AC_OUTPUT
+4
View File
@@ -0,0 +1,4 @@
changelog
control
*~
tmp
+1
View File
@@ -0,0 +1 @@
mbase for Debian
+5
View File
@@ -0,0 +1,5 @@
mbase (@PACKAGE_VERSION@-1) unstable; urgency=low
* Release.
-- Oleg Borodin <borodin@unix7.org> Sun, 29 Oct 2017 18:57:56 +0200
+1
View File
@@ -0,0 +1 @@
10
+15
View File
@@ -0,0 +1,15 @@
Source: mbase
Section: utils
Priority: extra
Maintainer: borodin@unix7.org
Build-Depends: debhelper (>=8)
Standards-Version: @PACKAGE_VERSION@
Homepage: http://wiki.unix7.org
Package: mbase-control
Description: mbase
Architecture: amd64
Package: mbase-service
Description: mbase
Architecture: amd64
+5
View File
@@ -0,0 +1,5 @@
mstore-control-dbgsym_2.11.0-1_amd64.deb debug optional automatic=yes
mstore-control_2.11.0-1_amd64.deb utils extra
mstore-service-dbgsym_2.11.0-1_amd64.deb debug optional automatic=yes
mstore-service_2.11.0-1_amd64.deb utils extra
mstore_2.11.0-1_amd64.buildinfo utils extra
+2
View File
@@ -0,0 +1,2 @@
usr/bin/mstorectl
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh -e
Vendored Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh -e
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh
set -e
case "$1" in
install|upgrade)
;;
abort-upgrade)
;;
*)
echo "preinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
#DEBHELPER#
exit 0
Vendored Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh -e
+6
View File
@@ -0,0 +1,6 @@
usr/sbin/mstored
lib/systemd/system/mstored.service
var/run/mstore
var/log/mstore
etc/mstore
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh -e
if [ "$1" = "configure" ] ; then
# Initial installation
systemctl preset mstored.service >/dev/null 2>&1 || :
fi
Vendored Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh -e
systemctl daemon-reload >/dev/null 2>&1 || :
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh
set -e
case "$1" in
install|upgrade)
;;
abort-upgrade)
;;
*)
echo "preinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
#DEBHELPER#
exit 0
Vendored Executable
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh -e
if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then
# Package removal, not upgrade
systemctl --no-reload disable mstored.service > /dev/null 2>&1 || :
systemctl stop mstored.service > /dev/null 2>&1 || :
fi
+1
View File
@@ -0,0 +1 @@
# You must remove unused comment lines for the released package.
Vendored Executable
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/make -f
export GO111MODULE=on
export GOPROXY=https://proxy.golang.org
%:
dh $@
override_dh_auto_configure:
./configure --prefix=/usr
#EOF
+1
View File
@@ -0,0 +1 @@
3.0 (quilt)
View File
+1
View File
@@ -0,0 +1 @@
version=3
+22
View File
@@ -0,0 +1,22 @@
MimeType: application/vnd.oci.image.manifest.v1+json
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.cncf.helm.config.v1+json",
"digest": "sha256:33e3759271a3c6dc018541cfb73653c267df6f8ee28ce68e38c72e22196a1d87",
"size": 126
},
"layers": [{
"mediaType": "application/vnd.cncf.helm.chart.content.v1.tar+gzip",
"digest": "sha256:93dc97d49c453a7ce3af622cf7ef698548045e0c09907c6a021018f6eac6c31a",
"size": 1528
}],
"annotations": {
"org.opencontainers.image.created": "2026-02-25T19:59:44+02:00",
"org.opencontainers.image.description": "mStore service",
"org.opencontainers.image.title": "mstore",
"org.opencontainers.image.version": "0.2.0"
}
}
+85
View File
@@ -0,0 +1,85 @@
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/27.0.9 Chrome/134.0.6998.205 Electron/35.4.0 Safari/537.36" version="27.0.9">
<diagram name="Page-1" id="bilFRRFyBUGthtbaxYIo">
<mxGraphModel dx="1880" dy="566" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" background="#ffffff" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="t6Klk0bs08zzC_b7PXua-28" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F0FDFF;glass=0;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="-10" y="55" width="120" height="335" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-26" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F0FDFF;glass=0;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="120" y="50" width="630" height="350" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-5" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-1" target="t6Klk0bs08zzC_b7PXua-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-30" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-2" target="t6Klk0bs08zzC_b7PXua-29">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-2" value="service" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="250" y="230" width="80" height="60" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-11" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;exitX=0.75;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-3" target="t6Klk0bs08zzC_b7PXua-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-19" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeColor=#0000CC;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-20" target="t6Klk0bs08zzC_b7PXua-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-3" value="handler" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
<mxGeometry x="390" y="150" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-7" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-6" target="t6Klk0bs08zzC_b7PXua-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-6" value="client" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad7ac;strokeColor=#b46504;" vertex="1" parent="1">
<mxGeometry x="10" y="240" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-12" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;strokeColor=#000099;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-8" target="t6Klk0bs08zzC_b7PXua-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-18" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-8" target="t6Klk0bs08zzC_b7PXua-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-23" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-8" target="t6Klk0bs08zzC_b7PXua-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-8" value="operator" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
<mxGeometry x="500" y="230" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-9" value="storage" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="570" y="300" width="90" height="50" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-10" value="lockers" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#bac8d3;strokeColor=#23445d;" vertex="1" parent="1">
<mxGeometry x="550" y="150" width="70" height="40" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-16" value="starter" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="140" y="110" width="80" height="50" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-33" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-1" target="t6Klk0bs08zzC_b7PXua-32">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-1" value="server" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="150" y="145" width="80" height="55" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-17" value="database" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="630" y="220" width="90" height="50" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-20" value="auth" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
<mxGeometry x="420" y="120" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-31" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="t6Klk0bs08zzC_b7PXua-29" target="t6Klk0bs08zzC_b7PXua-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-29" value="router" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
<mxGeometry x="290" y="140" width="70" height="50" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-32" value="config" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="290" y="70" width="70" height="40" as="geometry" />
</mxCell>
<mxCell id="t6Klk0bs08zzC_b7PXua-34" value="Feb 2026&lt;div&gt;O Borodin&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeColor=default;" vertex="1" parent="1">
<mxGeometry x="510" y="430" width="110" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+32
View File
@@ -0,0 +1,32 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:2f99832d1fc23ae7c8a35d5aa0b9d7a78a1876d69f9453d5d6e8701ac86c171c",
"size": 1357
},
"layers": [{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:7319607d119c259e90382101fb3ed98ad62e29ed817338183b3775dcfb358140",
"size": 3731518
}, {
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:1fccc5cb3c84a43c9dec4d89f1383471b41e1c4b9d4f271e3c952839f76634f5",
"size": 15791440
}, {
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:8cc3f2f15e1a38f6b733038dd9b3b27a88d4882a78a3235416f792dd9deca7af",
"size": 173
}],
"annotations": {
"com.docker.official-images.bashbrew.arch": "amd64",
"org.opencontainers.image.base.digest": "sha256:b0cb30c51c47cdfde647364301758b14c335dea2fddc9490d4f007d67ecb2538",
"org.opencontainers.image.base.name": "docker.io/library/alpine:3.20",
"org.opencontainers.image.created": "2026-01-28T01:18:13Z",
"org.opencontainers.image.revision": "b3f87708e5052e29737a251b2e9865e182dafe0c",
"org.opencontainers.image.source": "https://github.com/alpinelinux/docker-alpine.git#b3f87708e5052e29737a251b2e9865e182dafe0c:x86_64",
"org.opencontainers.image.url": "https://hub.docker.com/_/alpine",
"org.opencontainers.image.version": "3.20.9"
}
}
+54
View File
@@ -0,0 +1,54 @@
-----BEGIN CERTIFICATE-----
MIIEojCCBCmgAwIBAgISBpbPr7WFeCJ3U8QDioKGHkQiMAoGCCqGSM49BAMDMDIx
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
ODAeFw0yNjAyMTIwOTExMDVaFw0yNjA1MTMwOTExMDRaMBgxFjAUBgNVBAMTDWRl
di51bml4Ny5vcmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZnNwUA6M5kqmq
36oRkUTC+fSPlLiLDs3Vz6fPdYBWIokPKG+UqAS4WjfXXQEPwqGeoef0b5elB7dg
6GjwOhJio4IDNzCCAzMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
BwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFBme/mBwOaT6f4yzzCBc4i/NPQBY
MB8GA1UdIwQYMBaAFI8NE6L2Ln7RUGwzGDhdWY4jcpHKMDIGCCsGAQUFBwEBBCYw
JDAiBggrBgEFBQcwAoYWaHR0cDovL2U4LmkubGVuY3Iub3JnLzCCATUGA1UdEQSC
ASwwggEogg1haXIudW5peDcub3JnghJhaXJmb3JjZS51bml4Ny5vcmeCDWRldi51
bml4Ny5vcmeCDWVkdS51bml4Ny5vcmeCEGVkdW1heC51bml4Ny5vcmeCDWdpdC51
bml4Ny5vcmeCDWhhbS51bml4Ny5vcmeCDmhhc2gudW5peDcub3JnggxoZC51bml4
Ny5vcmeCDm1haWwudW5peDcub3Jnggxtdy51bml4Ny5vcmeCDG14LnVuaXg3Lm9y
Z4IOcGlraS51bml4Ny5vcmeCDHJtLnVuaXg3Lm9yZ4IQc3RvcmV4LnVuaXg3Lm9y
Z4INdzEyLnVuaXg3Lm9yZ4INdzEzLnVuaXg3Lm9yZ4IOd2lraS51bml4Ny5vcmeC
DXd3dy51bml4Ny5vcmcwEwYDVR0gBAwwCjAIBgZngQwBAgEwLQYDVR0fBCYwJDAi
oCCgHoYcaHR0cDovL2U4LmMubGVuY3Iub3JnLzM1LmNybDCCAQsGCisGAQQB1nkC
BAIEgfwEgfkA9wB1AGQRxGykEuyniRyiAi4AvKtPKAfUHjUnq+r+1QPJfc3wAAAB
nFFT2U0AAAQDAEYwRAIgbuNiYUqwgxi9Oycm2D6h8sclWLcBXHtqFWpwJT3dwbgC
IBBjMRcAmxZKE9PIgFqMvosPNQ7AAkbEfudVtqNkfwXJAH4Apcl4kl1XRheChw3Y
iWYLXFVki30AQPLsB2hR0YhpGfcAAAGcUVPcHQAIAAAFADH4c7UEAwBHMEUCIQDz
p9aYuw9jAZjxM8U3Qq7M4vFpp0GZDm80tpTdKYNjjwIgQ/e/lWg6uqQsjBytcaOG
IVXPEyB0n8fflOf+Ekh51DUwCgYIKoZIzj0EAwMDZwAwZAIwRrEAdYBcRU46Pold
w4VjUGnGsYEUqlsjrmn4awY01YGWknPaX5sTAI3hTuA32eOUAjA1dSANAAyO+icj
1ZiPZUGFjaMdkEu6Y/Ge8aueAUItNj9eF0ahlgZEnSlhHrswoZo=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQswCQYDVQQDEwJFODB2MBAGByqGSM49AgEGBSuBBAAiA2IABNFl8l7c
S7QMApzSsvru6WyrOq44ofTUOTIzxULUzDMMNMchIJBwXOhiLxxxs0LXeb5GDcHb
R6EToMffgSZjO9SNHfY9gjMy9vQr5/WWOrQTZxh7az6NSNnq3u2ubT6HTKOB+DCB
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFI8NE6L2Ln7RUGwzGDhdWY4j
cpHKMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBnE0hGINKsCYWi0Xx1ygxD5qihEjZ0
RI3tTZz1wuATH3ZwYPIp97kWEayanD1j0cDhIYzy4CkDo2jB8D5t0a6zZWzlr98d
AQFNh8uKJkIHdLShy+nUyeZxc5bNeMp1Lu0gSzE4McqfmNMvIpeiwWSYO9w82Ob8
otvXcO2JUYi3svHIWRm3+707DUbL51XMcY2iZdlCq4Wa9nbuk3WTU4gr6LY8MzVA
aDQG2+4U3eJ6qUF10bBnR1uuVyDYs9RhrwucRVnfuDj29CMLTsplM5f5wSV5hUpm
Uwp/vV7M4w4aGunt74koX71n4EdagCsL/Yk5+mAQU0+tue0JOfAV/R6t1k+Xk9s2
HMQFeoxppfzAVC04FdG9M+AC2JWxmFSt6BCuh3CEey3fE52Qrj9YM75rtvIjsm/1
Hl+u//Wqxnu1ZQ4jpa+VpuZiGOlWrqSP9eogdOhCGisnyewWJwRQOqK16wiGyZeR
xs/Bekw65vwSIaVkBruPiTfMOo0Zh4gVa8/qJgMbJbyrwwG97z/PRgmLKCDl8z3d
tA0Z7qq7fta0Gl24uyuB05dqI5J1LvAzKuWdIjT1tP8qCoxSE/xpix8hX2dt3h+/
jujUgFPFZ0EVZ0xSyBNRF3MboGZnYXFUxpNjTWPKpagDHJQmqrAcDmWJnMsFY3jS
u1igv3OefnWjSQ==
-----END CERTIFICATE-----
+5
View File
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOqwKQF1VWp3lSiIgD5E1ZNGXf/IlBLwEp8F+YooRiuGoAoGCCqGSM49
AwEHoUQDQgAE2ZzcFAOjOZKpqt+qEZFEwvn0j5S4iw7N1c+nz3WAViKJDyhvlKgE
uFo3110BD8KhnqHn9G+XpQe3YOho8DoSYg==
-----END EC PRIVATE KEY-----
+5
View File
@@ -0,0 +1,5 @@
certpath: mbased.crt
keypath: mbased.key
runUser: root
+118
View File
@@ -0,0 +1,118 @@
module mproxy
go 1.25.7
require (
github.com/dustin/go-humanize v1.0.1
github.com/google/go-containerregistry v0.21.3
github.com/google/uuid v1.6.0
github.com/jmoiron/sqlx v1.4.0
github.com/mattn/go-sqlite3 v1.14.38
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.1
github.com/spf13/cobra v1.10.2
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
go.yaml.in/yaml/v4 v4.0.0-rc.4
helm.sh/helm/v4 v4.1.3
sigs.k8s.io/yaml v1.6.0
)
require (
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/cli v29.3.0+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/extism/go-sdk v1.7.1 // indirect
github.com/fluxcd/cli-utils v0.37.2-flux.1 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-openapi/jsonpointer v0.21.1 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gofrs/flock v0.13.0 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.4 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
github.com/tetratelabs/wazero v1.11.0 // indirect
github.com/vbatts/tar-split v0.12.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.47.0 // indirect
golang.org/x/net v0.49.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/term v0.39.0 // indirect
golang.org/x/text v0.33.0 // indirect
golang.org/x/time v0.12.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.2 // indirect
k8s.io/api v0.35.1 // indirect
k8s.io/apiextensions-apiserver v0.35.1 // indirect
k8s.io/apimachinery v0.35.1 // indirect
k8s.io/cli-runtime v0.35.1 // indirect
k8s.io/client-go v0.35.1 // indirect
k8s.io/component-base v0.35.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
k8s.io/kubectl v0.35.1 // indirect
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
oras.land/oras-go/v2 v2.6.0 // indirect
sigs.k8s.io/controller-runtime v0.23.1 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/kustomize/api v0.21.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.21.1 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect
)
+384
View File
@@ -0,0 +1,384 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw=
github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v29.3.0+incompatible h1:z3iWveU7h19Pqx7alZES8j+IeFQZ1lhTwb2F+V9SVvk=
github.com/docker/cli v29.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a h1:UwSIFv5g5lIvbGgtf3tVwC7Ky9rmMFBp0RMs+6f6YqE=
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a/go.mod h1:C8DzXehI4zAbrdlbtOByKX6pfivJTBiV9Jjqv56Yd9Q=
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
github.com/extism/go-sdk v1.7.1 h1:lWJos6uY+tRFdlIHR+SJjwFDApY7OypS/2nMhiVQ9Sw=
github.com/extism/go-sdk v1.7.1/go.mod h1:IT+Xdg5AZM9hVtpFUA+uZCJMge/hbvshl8bwzLtFyKA=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fluxcd/cli-utils v0.37.2-flux.1 h1:tQ588ghtRN+E+kHq415FddfqA9v4brn/1WWgrP6rQR0=
github.com/fluxcd/cli-utils v0.37.2-flux.1/go.mod h1:LcWSu1NYET8d8U7O326RhEm5JkQXCMK6ITu4G1CT02c=
github.com/foxcpp/go-mockdns v1.2.0 h1:omK3OrHRD1IWJz1FuFBCFquhXslXoF17OvBS6JPzZF0=
github.com/foxcpp/go-mockdns v1.2.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-containerregistry v0.21.3 h1:Xr+yt3VvwOOn/5nJzd7UoOhwPGiPkYW0zWDLLUXqAi4=
github.com/google/go-containerregistry v0.21.3/go.mod h1:D5ZrJF1e6dMzvInpBPuMCX0FxURz7GLq2rV3Us9aPkc=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII=
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw=
github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca h1:T54Ema1DU8ngI+aef9ZhAhNGQhcRTrWxVeG07F+c/Rw=
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.38 h1:tDUzL85kMvOrvpCt8P64SbGgVFtJB11GPi2AdmITgb4=
github.com/mattn/go-sqlite3 v1.14.38/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q=
github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos=
github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM=
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho=
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U=
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc=
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ=
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 h1:ZF+QBjOI+tILZjBaFj3HgFonKXUcwgJ4djLb6i42S3Q=
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834/go.mod h1:m9ymHTgNSEjuxvw8E7WWe4Pl4hZQHXONY8wE6dMLaRk=
github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/bridges/prometheus v0.65.0 h1:I/7S/yWobR3QHFLqHsJ8QOndoiFsj1VgHpQiq43KlUI=
go.opentelemetry.io/contrib/bridges/prometheus v0.65.0/go.mod h1:jPF6gn3y1E+nozCAEQj3c6NZ8KY+tvAgSVfvoOJUFac=
go.opentelemetry.io/contrib/exporters/autoexport v0.65.0 h1:2gApdml7SznX9szEKFjKjM4qGcGSvAybYLBY319XG3g=
go.opentelemetry.io/contrib/exporters/autoexport v0.65.0/go.mod h1:0QqAGlbHXhmPYACG3n5hNzO5DnEqqtg4VcK5pr22RI0=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0 h1:ZVg+kCXxd9LtAaQNKBxAvJ5NpMf7LpvEr4MIZqb0TMQ=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0/go.mod h1:hh0tMeZ75CCXrHd9OXRYxTlCAdxcXioWHFIpYw2rZu8=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.16.0 h1:djrxvDxAe44mJUrKataUbOhCKhR3F8QCyWucO16hTQs=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.16.0/go.mod h1:dt3nxpQEiSoKvfTVxp3TUg5fHPLhKtbcnN3Z1I1ePD0=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.40.0 h1:NOyNnS19BF2SUDApbOKbDtWZ0IK7b8FJ2uAGdIWOGb0=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.40.0/go.mod h1:VL6EgVikRLcJa9ftukrHu/ZkkhFBSo1lzvdBC9CF1ss=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.40.0 h1:9y5sHvAxWzft1WQ4BwqcvA+IFVUJ1Ya75mSAUnFEVwE=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.40.0/go.mod h1:eQqT90eR3X5Dbs1g9YSM30RavwLF725Ris5/XSXWvqE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 h1:wVZXIWjQSeSmMoxF74LzAnpVQOAFDo3pPji9Y4SOFKc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0/go.mod h1:khvBS2IggMFNwZK/6lEeHg/W57h/IX6J4URh57fuI40=
go.opentelemetry.io/otel/exporters/prometheus v0.62.0 h1:krvC4JMfIOVdEuNPTtQ0ZjCiXrybhv+uOHMfHRmnvVo=
go.opentelemetry.io/otel/exporters/prometheus v0.62.0/go.mod h1:fgOE6FM/swEnsVQCqCnbOfRV4tOnWPg7bVeo4izBuhQ=
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.16.0 h1:ivlbaajBWJqhcCPniDqDJmRwj4lc6sRT+dCAVKNmxlQ=
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.16.0/go.mod h1:u/G56dEKDDwXNCVLsbSrllB2o8pbtFLUC4HpR66r2dc=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0/go.mod h1:3y6kQCWztq6hyW8Z9YxQDDm0Je9AJoFar2G0yDcmhRk=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0 h1:MzfofMZN8ulNqobCmCAVbqVL5syHw+eB2qPRkCMA/fQ=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0/go.mod h1:E73G9UFtKRXrxhBsHtG00TB5WxX57lpsQzogDkqBTz8=
go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4=
go.opentelemetry.io/otel/log v0.16.0/go.mod h1:rWsmqNVTLIA8UnwYVOItjyEZDbKIkMxdQunsIhpUMes=
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
go.opentelemetry.io/otel/sdk/log v0.16.0 h1:e/b4bdlQwC5fnGtG3dlXUrNOnP7c8YLVSpSfEBIkTnI=
go.opentelemetry.io/otel/sdk/log v0.16.0/go.mod h1:JKfP3T6ycy7QEuv3Hj8oKDy7KItrEkus8XJE6EoSzw4=
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U=
go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
helm.sh/helm/v4 v4.1.3 h1:Abfmb+oJUtxoaXDyB2Jhw1zRk3hT6aFfHta+AXb8Lno=
helm.sh/helm/v4 v4.1.3/go.mod h1:5dSo8rRgn3OTkDAc/k0Ipw5/Q+BlqKIKZwa0XwSiINI=
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w=
k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ=
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE=
k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw=
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE=
k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg=
k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc=
oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o=
sigs.k8s.io/controller-runtime v0.23.1 h1:TjJSM80Nf43Mg21+RCy3J70aj/W6KyvDtOlpKf+PupE=
sigs.k8s.io/controller-runtime v0.23.1/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs=
sigs.k8s.io/kustomize/api v0.21.1/go.mod h1:f3wkKByTrgpgltLgySCntrYoq5d3q7aaxveSagwTlwI=
sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7fI=
sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs=
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
+3
View File
@@ -0,0 +1,3 @@
*~
istored
istored.service
+24
View File
@@ -0,0 +1,24 @@
#!/bin/sh
#
# $Id$
#
# PROVIDE: mbased
# REQUIRE: DAEMON
. /etc/rc.subr
name="mbased"
rcvar="mbased_enable"
pidfile="/home/ziggi/Projects/mproxy/tmp/run/mbased.pid"
command="/usr/local/sbin/${name}"
command_args="--asDaemon=true"
procname="/usr/local/sbin/${name}"
load_rc_config ${name}
: ${mbased_enable:="NO"}
run_rc_command "$1"
#EOF
+24
View File
@@ -0,0 +1,24 @@
#!/bin/sh
#
# $Id$
#
# PROVIDE: mbased
# REQUIRE: DAEMON
. /etc/rc.subr
name="mbased"
rcvar="mbased_enable"
pidfile="@srv_rundir@/mbased.pid"
command="@prefix@/sbin/${name}"
command_args="--asDaemon=true"
procname="@prefix@/sbin/${name}"
load_rc_config ${name}
: ${mbased_enable:="NO"}
run_rc_command "$1"
#EOF
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=mbased
[Service]
Type=forking
PIDFile=/home/ziggi/Projects/mproxy/tmp/run/mbased.pid
ExecStart=/usr/local/sbin/mbased --asDaemon=true --port=443
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=mbased
[Service]
Type=forking
PIDFile=@srv_rundir@/mbased.pid
ExecStart=@prefix@/sbin/mbased --asDaemon=true --port=443
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
Executable
+541
View File
@@ -0,0 +1,541 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2024-06-19.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Report bugs to <bug-automake@gnu.org>.
GNU Automake home page: <https://www.gnu.org/software/automake/>.
General help using GNU software: <https://www.gnu.org/gethelp/>."
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 (GNU Automake) $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibility with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
+29
View File
@@ -0,0 +1,29 @@
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
dist_man1_MANS = \
mproxyctl.1 \
mproxyctl-accounts.1 \
mproxyctl-accounts-create.1 \
mproxyctl-accounts-delete.1 \
mproxyctl-accounts-get.1 \
mproxyctl-accounts-list.1 \
mproxyctl-accounts-update.1 \
mproxyctl-grants.1 \
mproxyctl-grants-create.1 \
mproxyctl-grants-delete.1 \
mproxyctl-grants-get.1 \
mproxyctl-grants-list.1 \
mproxyctl-grants-update.1
dist_man8_MANS = \
mproxyd.8
man:
$(GO) run makeman-mstorectl.go
$(GO) run makeman-mstored.go
EXTRA_DIST = \
makeman-mstorectl.go \
makeman-mstored.go
+585
View File
@@ -0,0 +1,585 @@
# Makefile.in generated by automake 1.17 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2024 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = mans
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
depcomp =
am__maybe_remake_depfiles =
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
{ test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
}
man1dir = $(mandir)/man1
am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)"
man8dir = $(mandir)/man8
NROFF = nroff
MANS = $(dist_man1_MANS) $(dist_man8_MANS)
am__extra_recursive_targets = docs-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(dist_man1_MANS) $(dist_man8_MANS) \
$(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BASENAME = @BASENAME@
CP = @CP@
CPIO = @CPIO@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DBUILDPACKAGE = @DBUILDPACKAGE@
DEFS = @DEFS@
DPKGSOURCE = @DPKGSOURCE@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
ETAGS = @ETAGS@
FIND = @FIND@
GO = @GO@
HAVE_GO = @HAVE_GO@
HELM = @HELM@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PODMAN = @PODMAN@
ROOT_GROUP = @ROOT_GROUP@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SORT = @SORT@
STRIP = @STRIP@
SUDO = @SUDO@
SWAG = @SWAG@
UNIQ = @UNIQ@
VERSION = @VERSION@
XARGS = @XARGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
am__leading_dot = @am__leading_dot@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
srv_confdir = @srv_confdir@
srv_datadir = @srv_datadir@
srv_devel_mode = @srv_devel_mode@
srv_libdir = @srv_libdir@
srv_logdir = @srv_logdir@
srv_rundir = @srv_rundir@
srv_sharedir = @srv_sharedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo
dist_man1_MANS = \
mproxyctl.1 \
mproxyctl-accounts.1 \
mproxyctl-accounts-create.1 \
mproxyctl-accounts-delete.1 \
mproxyctl-accounts-get.1 \
mproxyctl-accounts-list.1 \
mproxyctl-accounts-update.1 \
mproxyctl-grants.1 \
mproxyctl-grants-create.1 \
mproxyctl-grants-delete.1 \
mproxyctl-grants-get.1 \
mproxyctl-grants-list.1 \
mproxyctl-grants-update.1
dist_man8_MANS = \
mproxyd.8
EXTRA_DIST = \
makeman-mstorectl.go \
makeman-mstored.go
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign mans/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign mans/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-man1: $(dist_man1_MANS)
@$(NORMAL_INSTALL)
@list1='$(dist_man1_MANS)'; \
list2=''; \
test -n "$(man1dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.1[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
done; }
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list='$(dist_man1_MANS)'; test -n "$(man1dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
install-man8: $(dist_man8_MANS)
@$(NORMAL_INSTALL)
@list1='$(dist_man8_MANS)'; \
list2=''; \
test -n "$(man8dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.8[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
done; }
uninstall-man8:
@$(NORMAL_UNINSTALL)
@list='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
docs-local:
tags TAGS:
ctags CTAGS:
cscope cscopelist:
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(MANS)
installdirs:
for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
docs: docs-am
docs-am: docs-local
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-man
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man1 install-man8
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-man
uninstall-man: uninstall-man1 uninstall-man8
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
ctags-am distclean distclean-generic distdir docs-am \
docs-local dvi dvi-am html html-am info info-am install \
install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-man1 install-man8 install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
pdf-am ps ps-am tags-am uninstall uninstall-am uninstall-man \
uninstall-man1 uninstall-man8
.PRECIOUS: Makefile
man:
$(GO) run makeman-mstorectl.go
$(GO) run makeman-mstored.go
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
+49
View File
@@ -0,0 +1,49 @@
package main
import (
"fmt"
"os"
"time"
"github.com/spf13/cobra/doc"
"mproxy/cmd/mproxyctl/util"
)
func run() error {
var err error
os.Args[0] = "mproxyctl"
util := util.NewUtil()
err = util.Build()
if err != nil {
return err
}
cmd := util.GetRooCmd()
now := time.Now()
header := &doc.GenManHeader{
Title: "mproxyctl",
Section: "1",
Manual: "User commands",
Source: "mproxyctl command",
Date: &now,
}
opts := doc.GenManTreeOptions{
Header: header,
Path: "./",
CommandSeparator: "-",
}
err = doc.GenManTreeFromOpts(cmd, opts)
if err != nil {
return err
}
return err
}
func main() {
err := run()
if err != nil {
fmt.Printf("err: %v\n", err)
}
}
+48
View File
@@ -0,0 +1,48 @@
package main
import (
"fmt"
"os"
"time"
"github.com/spf13/cobra/doc"
"mproxy/cmd/mproxyd/starter"
)
func run() error {
var err error
os.Args[0] = "mproxyd"
util := starter.NewStarter()
if err != nil {
return err
}
cmd := util.GetCmd()
now := time.Now()
header := &doc.GenManHeader{
Title: "mproxyd",
Section: "8",
Manual: "User commands",
Source: "mproxyd command",
Date: &now,
}
opts := doc.GenManTreeOptions{
Header: header,
Path: "./",
CommandSeparator: "-",
}
err = doc.GenManTreeFromOpts(cmd, opts)
if err != nil {
return err
}
return err
}
func main() {
err := run()
if err != nil {
fmt.Printf("err: %v\n", err)
}
}
+23
View File
@@ -0,0 +1,23 @@
.nh
.TH "mproxyctl" "1" "May 2026" "mproxyctl command" "User commands"
.SH NAME
mproxyctl -
Operation with artefacts: files, images, service accounts and grants
.SH SYNOPSIS
\fBmproxyctl [flags]\fP
.SH DESCRIPTION
Operation with artefacts: files, images, service accounts and grants
.SH OPTIONS
\fB-h\fP, \fB--help\fP[=false]
help for mproxyctl
.SH HISTORY
26-May-2026 Auto generated by spf13/cobra
+31
View File
@@ -0,0 +1,31 @@
.nh
.TH "mproxyd" "8" "May 2026" "mproxyd command" "User commands"
.SH NAME
mproxyd -
Artifact storage service
.SH SYNOPSIS
\fBmproxyd [flags]\fP
.SH DESCRIPTION
Artifact storage service
.SH OPTIONS
\fB-D\fP, \fB--asDaemon\fP[=true]
Run service as daemon
.PP
\fB-h\fP, \fB--help\fP[=false]
help for mproxyd
.PP
\fB-P\fP, \fB--port\fP=1025
Service port
.SH HISTORY
26-May-2026 Auto generated by spf13/cobra
Executable
+236
View File
@@ -0,0 +1,236 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU and other programs.
scriptversion=2024-06-07.14; # UTC
# shellcheck disable=SC2006,SC2268 # we must support pre-POSIX shells
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autogen autoheader autom4te automake autoreconf
bison flex help2man lex makeinfo perl yacc
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Report bugs to <bug-automake@gnu.org>.
GNU Automake home page: <https://www.gnu.org/software/automake/>.
General help using GNU software: <https://www.gnu.org/gethelp/>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing (GNU Automake) $scriptversion"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=https://www.perl.org/
flex_URL=https://github.com/westes/flex
gnu_software_URL=https://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake|autoreconf)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
*)
:
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
autoheader_deps="'acconfig.h'"
automake_deps="'Makefile.am'"
aclocal_deps="'acinclude.m4'"
case $normalized_program in
aclocal*)
echo "You should only need it if you modified $aclocal_deps or"
echo "$configure_deps."
;;
autoconf*)
echo "You should only need it if you modified $configure_deps."
;;
autogen*)
echo "You should only need it if you modified a '.def' or '.tpl' file."
echo "You may want to install the GNU AutoGen package:"
echo "<$gnu_software_URL/autogen/>"
;;
autoheader*)
echo "You should only need it if you modified $autoheader_deps or"
echo "$configure_deps."
;;
automake*)
echo "You should only need it if you modified $automake_deps or"
echo "$configure_deps."
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
;;
autoreconf*)
echo "You should only need it if you modified $aclocal_deps or"
echo "$automake_deps or $autoheader_deps or $automake_deps or"
echo "$configure_deps."
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
perl*)
echo "You should only need it to run GNU Autoconf, GNU Automake, "
echo " assorted other tools, or if you modified a Perl source file."
echo "You may want to install the Perl 5 language interpreter:"
echo "<$perl_URL>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
program_details "$normalized_program"
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
*
*/
package auxhttp
import (
"encoding/base64"
"fmt"
"strings"
)
func EncodeBasicAuth(username, password string) string {
auth := username + ":" + password
return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
}
func ParseBasicAuth(basicFields string) (string, string, error) {
var err error
var username string
var password string
if basicFields == "" {
err := fmt.Errorf("Empty auth field")
return username, password, err
}
authFields := strings.SplitN(basicFields, " ", 2)
if len(authFields) < 2 {
err = fmt.Errorf("Cannot split auth field: %s", basicFields)
return username, password, err
}
authType := strings.TrimSpace(authFields[0])
if strings.ToLower(authType) != strings.ToLower("Basic") {
err = fmt.Errorf("Not basic auth type")
return username, password, err
}
authPairEncoded := authFields[1]
pairEncoded, err := base64.StdEncoding.DecodeString(authPairEncoded)
if err != nil {
err = fmt.Errorf("Cannon decode auth pair")
return username, password, err
}
authPair := strings.SplitN(string(pairEncoded), ":", 2)
if len(authPair) != 2 {
err = fmt.Errorf("Wrong auth pair")
return username, password, err
}
username = authPair[0]
password = authPair[1]
return username, password, err
}
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
*
*/
package auxhttp
import (
"fmt"
"strconv"
"strings"
)
func ParseOCIContentRange(ref string) (int64, int64, error) {
var start, end int64
var err error
startstop := strings.TrimSpace(ref)
tmp := strings.SplitN(startstop, "-", 2)
if len(tmp) != 2 {
err = fmt.Errorf("Wrong Content-Range definition, strange range def %v", startstop)
return start, end, err
}
startstr := tmp[0]
endstr := tmp[1]
start, err = strconv.ParseInt(startstr, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Range definition, strange start %s", startstr)
return start, end, err
}
end, err = strconv.ParseInt(endstr, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Range definition, strange end %s", endstr)
return start, end, err
}
return start, end, err
}
func ParseContentRange(ref string) (int64, int64, int64, error) {
var start, end, total int64
var err error
const bytesUnit = "bytes"
tmp := strings.SplitN(ref, " ", 2)
if len(tmp) != 2 {
err := fmt.Errorf("Wrong Content-Range definition, len is only %d", len(tmp))
return start, end, total, err
}
unit := strings.ToLower(tmp[0])
if unit != bytesUnit {
err = fmt.Errorf("Wrong Content-Range definition, strange length def %s", unit)
return start, end, total, err
}
ranger := strings.TrimSpace(tmp[1])
tmp = strings.Split(ranger, "/")
if len(tmp) != 2 {
err = fmt.Errorf("Wrong Content-Range definition, dont found total")
return start, end, total, err
}
totalstr := tmp[1]
if totalstr == "*" {
total = 0
} else {
total, err = strconv.ParseInt(totalstr, 10, 64)
if err != nil {
return start, end, total, err
}
}
startstop := tmp[0]
tmp = strings.SplitN(startstop, "-", 2)
if len(tmp) != 2 {
err = fmt.Errorf("Wrong Content-Range definition, strange range def %v", startstop)
return start, end, total, err
}
startstr := tmp[0]
endstr := tmp[1]
start, err = strconv.ParseInt(startstr, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Range definition, strange start %s", startstr)
return start, end, total, err
}
end, err = strconv.ParseInt(endstr, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Range definition, strange end %s", endstr)
return start, end, total, err
}
return start, end, total, err
}
+107
View File
@@ -0,0 +1,107 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxpwd
import (
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"fmt"
"math/rand"
"strings"
"time"
)
var rnd *rand.Rand
const (
sha256Prefix = "sha256pwd"
sha512Prefix = "sha512pwd"
saltSize = 16
)
func init() {
src := rand.NewSource(time.Now().UnixNano())
rnd = rand.New(src)
}
func MakeSHA256Hash(passwd []byte) string {
var res string
salt := hex.EncodeToString(randomBytes(saltSize))
passwdString := hex.EncodeToString(passwd)
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
hasher := sha256.New()
hasher.Write([]byte(passwdString))
checksum := hex.EncodeToString(hasher.Sum(nil))
res = fmt.Sprintf("%s:%s:%s", sha256Prefix, salt, checksum)
return res
}
func MakeSHA512Hash(passwd []byte) string {
var res string
salt := hex.EncodeToString(randomBytes(saltSize))
passwdString := hex.EncodeToString(passwd)
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
hasher := sha512.New()
hasher.Write([]byte(passwdString))
checksum := hex.EncodeToString(hasher.Sum(nil))
res = fmt.Sprintf("%s:%s:%s", sha512Prefix, salt, checksum)
return res
}
func PasswordMatch(passwd []byte, hash string) bool {
hashComponents := strings.Split(hash, ":")
if len(hashComponents) != 3 {
return false
}
method := hashComponents[0]
salt := hashComponents[1]
controlChecksum := hashComponents[2]
switch method {
case sha256Prefix:
passwdString := hex.EncodeToString(passwd)
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
hasher := sha256.New()
hasher.Write([]byte(passwdString))
checksum := hex.EncodeToString(hasher.Sum(nil))
if checksum != controlChecksum {
return false
}
case sha512Prefix:
passwdString := hex.EncodeToString(passwd)
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
hasher := sha512.New()
hasher.Write([]byte(passwdString))
checksum := hex.EncodeToString(hasher.Sum(nil))
if checksum != controlChecksum {
return false
}
default:
return false
}
return true
}
func randomString(n int) string {
const letters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
arr := make([]byte, n)
lettersArrayLen := len(letters)
for i := range arr {
arr[i] = letters[rnd.Intn(lettersArrayLen)]
}
return string(arr)
}
func randomBytes(n int) []byte {
arr := make([]byte, n)
for i := range arr {
arr[i] = byte(rnd.Intn(256) & 0xFF)
}
return arr
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxpwd
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func TestPasswd256(t *testing.T) {
password := []byte("123456789")
wrongPasswd := []byte("qwerty")
hash := MakeSHA256Hash(password)
fmt.Printf("%s\n", hash)
{
match := PasswordMatch(password, hash)
require.Equal(t, true, match)
}
{
match := PasswordMatch(wrongPasswd, hash)
require.NotEqual(t, true, match)
}
}
func TestPasswd512(t *testing.T) {
password := []byte("123456781")
wrongPasswd := []byte("qwerty")
hash := MakeSHA512Hash(password)
fmt.Printf("%s\n", hash)
{
match := PasswordMatch(password, hash)
require.Equal(t, true, match)
}
{
match := PasswordMatch(wrongPasswd, hash)
require.NotEqual(t, true, match)
}
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxtool
import (
"os"
"path/filepath"
"strings"
)
// Clean only overbase elements of dir path if possible
func CleanDirs(basedir, datadir string) {
separator := string(os.PathSeparator)
basedir = filepath.Clean(separator + basedir)
datadir = filepath.Clean(separator + datadir)
items := strings.Split(datadir, separator)
for i := len(items); i > 0; i-- {
p := filepath.Join(items[0:i]...)
p = filepath.Clean(separator + p)
if p == basedir {
break
}
fileInfo, err := os.Stat(p)
if err != nil {
return
}
if fileInfo.IsDir() {
err = os.Remove(p)
if err != nil {
return
}
}
}
}
+31
View File
@@ -0,0 +1,31 @@
package auxtool
import (
"os"
)
func FileExists(name string) bool {
fileStat, err := os.Stat(name)
if err != nil {
if os.IsNotExist(err) {
return false
}
}
if fileStat.IsDir() {
return false
}
return true
}
func DirExists(name string) bool {
fileStat, err := os.Stat(name)
if err != nil {
if os.IsNotExist(err) {
return false
}
}
if fileStat == nil {
return false
}
return fileStat.IsDir()
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
*
*/
/*
*/
package auxtool
import (
"math/rand"
)
func RandomString(n int) string {
const letters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
arr := make([]byte, n)
for i := range arr {
arr[i] = letters[rand.Intn(len(letters))]
}
return string(arr)
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxtool
import (
"encoding/hex"
"fmt"
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func MakeTmpFilename(prefix string) string {
randBytes := make([]byte, 6)
rand.Read(randBytes)
suffix := hex.EncodeToString(randBytes)
return fmt.Sprintf("%s.tmp.%s", prefix, suffix)
}
+13
View File
@@ -0,0 +1,13 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxtool
import (
"time"
)
func TimeNow() string {
return time.Now().Format(time.RFC3339)
}
+151
View File
@@ -0,0 +1,151 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxutar
import (
"archive/tar"
"io"
"os"
"path/filepath"
"strings"
"time"
)
func Archive(srcdir, dstpath string) error {
var err error
srcdir = filepath.Clean(srcdir)
dstpath = filepath.Clean(dstpath)
err = os.MkdirAll(filepath.Dir(dstpath), 0750)
if err != nil {
return err
}
tarFile, err := os.OpenFile(dstpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
if err != nil {
return err
}
defer tarFile.Close()
tarWriter := tar.NewWriter(tarFile)
defer tarWriter.Close()
walker := func(filename string, fileInfo os.FileInfo, err error) error {
if err != nil {
return err
}
if !fileInfo.Mode().IsRegular() {
return nil
}
header, err := tar.FileInfoHeader(fileInfo, fileInfo.Name())
if err != nil {
return err
}
header.Name = strings.TrimPrefix(filename, filepath.Clean(srcdir))
header.Name = strings.TrimPrefix(header.Name, string(filepath.Separator))
err = tarWriter.WriteHeader(header)
if err != nil {
return err
}
wrapfunc := func() error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(tarWriter, file)
if err != nil {
return err
}
return err
}
err = wrapfunc()
if err != nil {
return err
}
return nil
}
err = filepath.Walk(srcdir, walker)
if err != nil {
return err
}
return err
}
func Unarchive(filename, dstdir string) error {
var err error
err = os.MkdirAll(dstdir, 0755)
if err != nil {
return err
}
file, err := os.OpenFile(filename, os.O_RDONLY, 0)
if err != nil {
return err
}
defer file.Close()
tarReader := tar.NewReader(file)
for {
header, err := tarReader.Next()
switch {
case err == io.EOF:
return nil
case err != nil:
return err
case header == nil:
continue
}
target := filepath.Join(dstdir, header.Name)
target = filepath.Clean(target)
fileInfo := header.FileInfo()
switch header.Typeflag {
case tar.TypeDir:
_, err := os.Stat(target)
if os.IsNotExist(err) {
err = nil
err := os.MkdirAll(target, fileInfo.Mode())
if err != nil {
return err
}
}
if err != nil {
return err
}
case tar.TypeReg:
wrapfunc := func() error {
dir := filepath.Dir(target)
_, err := os.Stat(dir)
if os.IsNotExist(err) {
err := os.MkdirAll(dir, 0750)
if err != nil {
return err
}
}
file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, fileInfo.Mode())
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(file, tarReader)
if err != nil {
return err
}
return err
}
err = wrapfunc()
if err != nil {
return err
}
}
err = os.Chtimes(target, time.Now(), fileInfo.ModTime())
if err != nil {
return err
}
err = file.Chmod(fileInfo.Mode())
if err != nil {
return err
}
}
return err
}
+14
View File
@@ -0,0 +1,14 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxuuid
import (
"github.com/google/uuid"
)
const ZeroUUID string = "00000000-0000-0000-0000-000000000000"
func NewUUID() string {
return uuid.New().String()
}
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxx509
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"time"
)
func CreateSelfSignedCert(subject string, dnsNames ...string) ([]byte, []byte, error) {
var err error
certPem := make([]byte, 0)
keyPem := make([]byte, 0)
now := time.Now()
const yearsAfter int = 10
const keySize int = 2048
key, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
err := fmt.Errorf("Can't create a private key: %v", err)
return certPem, keyPem, err
}
keyPemBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
keyPem = pem.EncodeToMemory(&keyPemBlock)
names := make([]string, 0)
names = append(names, subject)
names = append(names, dnsNames...)
tml := x509.Certificate{
SerialNumber: big.NewInt(now.Unix()),
NotBefore: now,
NotAfter: now.AddDate(yearsAfter, 0, 0),
Subject: pkix.Name{
CommonName: subject,
},
DNSNames: names,
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
if err != nil {
return certPem, keyPem, fmt.Errorf("Can't create a certificate: %v", err)
}
certPemBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certPem = pem.EncodeToMemory(&certPemBlock)
if err != nil {
return certPem, keyPem, err
}
return certPem, keyPem, err
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package auxx509
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func TestCert(t *testing.T) {
caCert, caKey, err := CreateSelfSignedCert("test1")
require.NoError(t, err)
fmt.Println(string(caCert))
fmt.Println(string(caKey))
}
+417
View File
@@ -0,0 +1,417 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
* This work is published and licensed under a Creative Commons
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
*
* Distribution of this work is permitted, but commercial use and
* modifications are strictly prohibited.
*/
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"mproxy/pkg/auxhttp"
"mproxy/pkg/descr"
)
func (cli *Client) FileInfo(ctx context.Context, fileuri string) (bool, *descr.File, error) {
var exists bool
var err error
file := &descr.File{}
fileuri, username, password, err := repackServiceURI(fileuri)
if err != nil {
return exists, file, err
}
fileuri, err = convertFileURI(fileuri)
if err != nil {
return exists, file, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodHead, fileuri, nil)
if err != nil {
return exists, file, err
}
if username != "" && password != "" {
basic := auxhttp.EncodeBasicAuth(username, password)
req.Header.Add("Authorization", basic)
}
client := makeHTTPClient(cli.skipTLSVerify)
resp, err := client.Do(req)
if err != nil {
return exists, file, err
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
file.Collection = resp.Header.Get("Content-Collection")
file.Name = resp.Header.Get("Content-Name")
contentSize := resp.Header.Get("Content-Size")
size, err := strconv.ParseInt(contentSize, 10, 64)
if err != nil {
return exists, file, err
}
file.Size = size
file.Type = resp.Header.Get("Content-Type")
file.Checksum = resp.Header.Get("Content-Digest")
exists = true
}
return exists, file, err
}
func (cli *Client) PutFile(ctx context.Context, filename, fileuri string) error {
var err error
fileuri, username, password, err := repackServiceURI(fileuri)
if err != nil {
return err
}
fileuri, err = convertFileURI(fileuri)
if err != nil {
return err
}
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fileuri, file)
if err != nil {
return err
}
fileinfo, err := os.Stat(filename)
if err != nil {
return err
}
filesize := fileinfo.Size()
req.ContentLength = filesize
req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Content-Size", strconv.FormatInt(filesize, 10))
if username != "" && password != "" {
basic := auxhttp.EncodeBasicAuth(username, password)
req.Header.Add("Authorization", basic)
}
client := makeHTTPClient(cli.skipTLSVerify)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
return err
}
return err
}
func (cli *Client) GetFile(ctx context.Context, fileuri, filename string) (int64, error) {
var err error
var size int64
fileuri, username, password, err := repackServiceURI(fileuri)
if err != nil {
return size, err
}
fileuri, err = convertFileURI(fileuri)
if err != nil {
return size, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileuri, nil)
if err != nil {
return size, err
}
if username != "" && password != "" {
basic := auxhttp.EncodeBasicAuth(username, password)
req.Header.Add("Authorization", basic)
}
client := makeHTTPClient(cli.skipTLSVerify)
resp, err := client.Do(req)
if err != nil {
return size, err
}
defer resp.Body.Close()
contentLength := resp.Header.Get("Content-Length")
if contentLength == "" {
err = fmt.Errorf("Empty Content-Length received")
return size, err
}
if resp.StatusCode != http.StatusOK {
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
return size, err
}
declSize, err := strconv.ParseInt(contentLength, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Length value: %v", err)
return size, err
}
dirname := filepath.Dir(filename)
err = os.MkdirAll(dirname, 0750)
if err != nil {
return size, err
}
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0640)
if err != nil {
return size, err
}
size, err = io.Copy(file, resp.Body)
if err != nil {
return size, err
}
if size != declSize {
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
return size, err
}
return size, err
}
func (cli *Client) DeleteFile(ctx context.Context, fileuri string) error {
var err error
fileuri, username, password, err := repackServiceURI(fileuri)
if err != nil {
return err
}
fileuri, err = convertFileURI(fileuri)
if err != nil {
return err
}
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fileuri, nil)
if err != nil {
return err
}
if username != "" && password != "" {
basic := auxhttp.EncodeBasicAuth(username, password)
req.Header.Add("Authorization", basic)
}
client := makeHTTPClient(cli.skipTLSVerify)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
return err
}
return err
}
func (cli *Client) ListFiles(ctx context.Context, catalogURI, usePathAs string) ([]descr.File, error) {
var err error
res := make([]descr.File, 0)
catalogURI, username, password, err := repackServiceURI(catalogURI)
if err != nil {
return res, err
}
catalogURI, err = convertFilesURI(catalogURI)
if err != nil {
return res, err
}
// Add values
values := url.Values{}
if usePathAs != "" {
values.Add("pathAs", string(usePathAs))
}
encodedValues := values.Encode()
if encodedValues != "" {
catalogURI = catalogURI + "?" + encodedValues
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, catalogURI, nil)
if err != nil {
return res, err
}
if username != "" && password != "" {
basic := auxhttp.EncodeBasicAuth(username, password)
req.Header.Add("Authorization", basic)
}
client := makeHTTPClient(cli.skipTLSVerify)
resp, err := client.Do(req)
if err != nil {
return res, err
}
defer resp.Body.Close()
contentLength := resp.Header.Get("Content-Length")
if contentLength == "" {
err = fmt.Errorf("Empty Content-Length received")
return res, err
}
if resp.StatusCode != http.StatusOK {
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
return res, err
}
declSize, err := strconv.ParseInt(contentLength, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Length value: %v", err)
return res, err
}
respBuffer := bytes.NewBuffer(nil)
size, err := io.Copy(respBuffer, resp.Body)
if err != nil {
return res, err
}
respBytes := respBuffer.Bytes()
if size != declSize {
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
return res, err
}
err = json.Unmarshal(respBytes, &res)
if err != nil {
return res, err
}
return res, err
}
func (cli *Client) ListCollections(ctx context.Context, catalogURI, usePathAs string) ([]string, error) {
var err error
res := make([]string, 0)
catalogURI, username, password, err := repackServiceURI(catalogURI)
if err != nil {
return res, err
}
catalogURI, err = convertCollectionsURI(catalogURI)
if err != nil {
return res, err
}
// Add values
values := url.Values{}
if usePathAs != "" {
values.Add("pathAs", string(usePathAs))
}
encodedValues := values.Encode()
if encodedValues != "" {
catalogURI = catalogURI + "?" + encodedValues
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, catalogURI, nil)
if err != nil {
return res, err
}
if username != "" && password != "" {
basic := auxhttp.EncodeBasicAuth(username, password)
req.Header.Add("Authorization", basic)
}
client := makeHTTPClient(cli.skipTLSVerify)
resp, err := client.Do(req)
if err != nil {
return res, err
}
defer resp.Body.Close()
contentLength := resp.Header.Get("Content-Length")
if contentLength == "" {
err = fmt.Errorf("Empty Content-Length received")
return res, err
}
if resp.StatusCode != http.StatusOK {
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
return res, err
}
declSize, err := strconv.ParseInt(contentLength, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Length value: %v", err)
return res, err
}
respBuffer := bytes.NewBuffer(nil)
size, err := io.Copy(respBuffer, resp.Body)
if err != nil {
return res, err
}
respBytes := respBuffer.Bytes()
if size != declSize {
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
return res, err
}
err = json.Unmarshal(respBytes, &res)
if err != nil {
return res, err
}
return res, err
}
func (cli *Client) DeleteCollection(ctx context.Context, catalogURI, usePathAs string, dryRun bool) ([]descr.File, error) {
var err error
res := make([]descr.File, 0)
catalogURI, username, password, err := repackServiceURI(catalogURI)
if err != nil {
return res, err
}
catalogURI, err = convertCollectionURI(catalogURI)
if err != nil {
return res, err
}
// Add values
values := url.Values{}
if usePathAs != "" {
values.Add("pathAs", string(usePathAs))
}
if dryRun {
values.Add("dryRun", "true")
}
encodedValues := values.Encode()
if encodedValues != "" {
catalogURI = catalogURI + "?" + encodedValues
}
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, catalogURI, nil)
if err != nil {
return res, err
}
if username != "" && password != "" {
basic := auxhttp.EncodeBasicAuth(username, password)
req.Header.Add("Authorization", basic)
}
client := makeHTTPClient(cli.skipTLSVerify)
resp, err := client.Do(req)
if err != nil {
return res, err
}
defer resp.Body.Close()
contentLength := resp.Header.Get("Content-Length")
if contentLength == "" {
err = fmt.Errorf("Empty Content-Length received")
return res, err
}
if resp.StatusCode != http.StatusOK {
err := fmt.Errorf("Received wrong status code: %s", resp.Status)
return res, err
}
declSize, err := strconv.ParseInt(contentLength, 10, 64)
if err != nil {
err = fmt.Errorf("Wrong Content-Length value: %v", err)
return res, err
}
respBuffer := bytes.NewBuffer(nil)
size, err := io.Copy(respBuffer, resp.Body)
if err != nil {
return res, err
}
respBytes := respBuffer.Bytes()
if size != declSize {
err := fmt.Errorf("Mismatch Content-Length and recorded filesize")
return res, err
}
err = json.Unmarshal(respBytes, &res)
if err != nil {
return res, err
}
return res, err
}
+131
View File
@@ -0,0 +1,131 @@
package servcli
import (
"crypto/tls"
"encoding/base64"
"net/http"
)
type Client struct {
httpClient *http.Client
userAgent string
}
func NewClient(transport http.RoundTripper, mwFuncs ...MiddlewareFunc) *Client {
if transport == nil {
transport = NewDefaultTransport()
}
for _, mwFunc := range mwFuncs {
transport = mwFunc(transport)
}
httpClient := &http.Client{
Transport: transport,
}
return &Client{
httpClient: httpClient,
userAgent: "ociClient/1.0",
}
}
func (cli *Client) SetTransport(transport http.RoundTripper) {
cli.httpClient.Transport = transport
}
type MiddlewareFunc func(next http.RoundTripper) http.RoundTripper
func (cli *Client) UseMiddleware(mwFunc MiddlewareFunc) {
cli.httpClient.Transport = mwFunc(cli.httpClient.Transport)
}
// BasicAuthMiddleware
func NewBasicAuthMiddleware(user, pass string) MiddlewareFunc {
return func(next http.RoundTripper) http.RoundTripper {
return newBasicAuthMW(next, user, pass)
}
}
type BasicAuthMW struct {
user, pass string
next http.RoundTripper
}
func newBasicAuthMW(next http.RoundTripper, user, pass string) *BasicAuthMW {
return &BasicAuthMW{
user: user,
pass: pass,
next: next,
}
}
func (tran BasicAuthMW) RoundTrip(req *http.Request) (*http.Response, error) {
if tran.user != "" && tran.pass != "" {
pair := base64.StdEncoding.EncodeToString([]byte(tran.user + ":" + tran.pass))
req.Header.Set("Authorization", "Basic "+pair)
}
return tran.next.RoundTrip(req)
}
// BearerAuthMiddleware
func NewBearerAuthMiddleware(token string) MiddlewareFunc {
return func(next http.RoundTripper) http.RoundTripper {
return newBearerAuthMW(next, token)
}
}
type BearerAuthMW struct {
token string
next http.RoundTripper
}
func newBearerAuthMW(next http.RoundTripper, token string) *BearerAuthMW {
return &BearerAuthMW{
token: token,
next: next,
}
}
func (tran BearerAuthMW) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("Authorization", "Bearer "+tran.token)
return tran.next.RoundTrip(req)
}
// DefaultTransport
type DefaultTransport struct {
transport http.RoundTripper
}
func NewDefaultTransport() *DefaultTransport {
return &DefaultTransport{
transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
}
func (wrap *DefaultTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return wrap.transport.RoundTrip(req)
}
// ExampleMiddleware
func NewExampleMiddleware() MiddlewareFunc {
return func(next http.RoundTripper) http.RoundTripper {
return newExampleTransport(next)
}
}
type ExampleTransport struct {
next http.RoundTripper
}
func newExampleTransport(next http.RoundTripper) *ExampleTransport {
return &ExampleTransport{
next: next,
}
}
func (tran ExampleTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return tran.next.RoundTrip(req)
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*/
package servcli
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"strconv"
)
func (cli *Client) doHTTPCall(ctx context.Context, host, obj, oper string, req []byte) ([]byte, error) {
var err error
var res []byte
reader := bytes.NewReader(req)
ref, err := NewReferer(host, obj, oper)
if err != nil {
return res, err
}
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, ref.Point(), reader)
if err != nil {
return res, err
}
httpReq.Header.Set("User-Agent", cli.userAgent)
httpReq.Header.Set("Accept", "*/*")
httpResp, err := cli.httpClient.Do(httpReq)
if err != nil {
return res, err
}
defer httpResp.Body.Close()
if httpResp.StatusCode != http.StatusOK {
err := fmt.Errorf("Unexpected response code: %s", httpResp.Status)
return res, err
}
contentLength := httpResp.Header.Get("Content-Length")
if contentLength == "" {
err := fmt.Errorf("Content-Length header is missing")
return res, err
}
blobSize, err := strconv.ParseInt(contentLength, 10, 64)
if err != nil {
return res, err
}
buffer := bytes.NewBuffer(nil)
recSize, err := io.Copy(buffer, httpResp.Body)
if blobSize != recSize {
err := fmt.Errorf("Mismatch declared and actual body size, %d and %d", blobSize, recSize)
return res, err
}
res = buffer.Bytes()
return res, err
}

Some files were not shown because too many files have changed in this diff Show More