commit bc4c3fafc16b1db0226943351dac7f144c205b8a
parent 29b8ceb193d4ffacc2a262228536018494ccd6b0
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Sun, 27 Apr 2025 00:41:35 +0200
fix libtool vs package version; vendor base32
Diffstat:
9 files changed, 174 insertions(+), 34 deletions(-)
diff --git a/Makefile.in b/Makefile.in
@@ -1,15 +1,15 @@
all: server #cli
-VERSION="1:0:0"
TALER_MAILBOX_HOME=${datadir}/taler-mailbox
+LT_VERSION="1:0:0"
server:
- ${GO} build -ldflags "-X main.version=${VERSION} -X main.mailboxdatahome=${TALER_MAILBOX_HOME}" -o taler-mailbox ./cmd/mailbox-server
+ ${GO} build -ldflags "-X main.ltversion=${LT_VERSION} -X main.version=${VERSION} -X main.mailboxdatahome=${TALER_MAILBOX_HOME}" -o taler-mailbox ./cmd/mailbox-server
#cli:
# go build ./cmd/mailbox-cli
-install: server gana
+install: server
mkdir -p ${DESTDIR}${bindir}
mkdir -p ${DESTDIR}${TALER_MAILBOX_HOME}
install ./taler-mailbox ${DESTDIR}${bindir}
diff --git a/bootstrap b/bootstrap
@@ -12,6 +12,8 @@ if ! existence go; then
exit 1
fi
-mkdir -p internal/gana
-git submodule update --init --recursive
-git submodule sync --recursive
+if [ -d ".git" ]; then
+ mkdir -p internal/gana
+ git submodule update --init --recursive
+ git submodule sync --recursive
+fi
diff --git a/cmd/mailbox-server/main.go b/cmd/mailbox-server/main.go
@@ -34,6 +34,7 @@ import (
var (
m mailbox.Mailbox
+ ltversion string
version string
mailboxdatahome string
verbose bool
@@ -85,6 +86,7 @@ func main() {
merchToken := iniCfg.Section("mailbox").Key("merchant_token").MustString("secretAccessToken")
merch := merchant.NewMerchant(merchURL, merchToken)
m.Initialize(mailbox.MailboxConfig{
+ LibtoolVersion: ltversion,
Version: version,
Datahome: mailboxdatahome,
Db: db,
diff --git a/cmd/mailbox-server/main_test.go b/cmd/mailbox-server/main_test.go
@@ -14,12 +14,12 @@ import (
"strings"
"testing"
- gnunetutil "git.gnunet.org/gnunet-go.git/pkg/util"
"github.com/schanzen/taler-go/pkg/merchant"
- "github.com/schanzen/taler-go/pkg/util"
+ talerutil "github.com/schanzen/taler-go/pkg/util"
"gopkg.in/ini.v1"
"gorm.io/driver/sqlite"
"taler.net/taler-mailbox/internal/gana"
+ "taler.net/taler-mailbox/internal/util"
"taler.net/taler-mailbox/pkg/rest"
)
@@ -115,7 +115,7 @@ func TestMain(m *testing.M) {
testWalletAlice, testWalletAlicePriv, _ = ed25519.GenerateKey(nil)
h := sha512.New()
h.Write(testWalletAlice)
- testWalletAliceString = gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ testWalletAliceString = util.Base32CrockfordEncode(h.Sum(nil))
a.Merchant = merchant.NewMerchant(merchServer.URL, "")
@@ -156,7 +156,7 @@ func TestPostMessagePaid(t *testing.T) {
testMessage := make([]byte, 256)
// Make paid
- fee, err := util.ParseAmount("KUDOS:1")
+ fee, err := talerutil.ParseAmount("KUDOS:1")
if err != nil {
t.Errorf("%v", err)
}
@@ -179,7 +179,7 @@ func TestPostMessagePaid(t *testing.T) {
if body != "" {
t.Errorf("Expected empty response, Got %s", body)
}
- a.MessageFee, _ = util.ParseAmount("KUDOS:0")
+ a.MessageFee, _ = talerutil.ParseAmount("KUDOS:0")
}
func TestPostThenDeleteMessage(t *testing.T) {
@@ -234,12 +234,12 @@ func TestPostThenDeleteMessage(t *testing.T) {
if !ed25519.Verify(testWalletAlice, signed_msg[0:], sig) {
t.Errorf("Signature invalid!")
}
- deletionReq.WalletSig = gnunetutil.EncodeBinaryToString(sig)
+ deletionReq.WalletSig = util.Base32CrockfordEncode(sig)
deletionReq.Count = int(a.MessageResponseLimit)
- deletionReq.Checksum = gnunetutil.EncodeBinaryToString(checksum)
+ deletionReq.Checksum = util.Base32CrockfordEncode(checksum)
reqJson, _ := json.Marshal(deletionReq)
- hAddress := gnunetutil.EncodeBinaryToString(testWalletAlice)
+ hAddress := util.Base32CrockfordEncode(testWalletAlice)
req, _ = http.NewRequest("DELETE", "/"+hAddress, bytes.NewBuffer(reqJson))
req.Header.Add("If-Match", etag)
response = executeRequest(req)
diff --git a/configure b/configure
@@ -12,6 +12,21 @@ standard_flags="ARFLAGS BISONFLAGS CFLAGS CXXFLAGS CPPFLAGS FLEXFLAGS INSTALLFLA
standard_vars="INSTALL_DATA INSTALL_PROGRAM INSTALL_SCRIPT"
generated_comment="# This file was generated by configure. DO NOT edit it directly."
+if [ -d ".git" ]; then
+ detected_version=`git describe --tags`
+ detected_version=${detected_version:1}
+else
+ dirnm=${PWD##*/}
+ dirnm=${dirnm:-/}
+ detected_version=${dirnm#*-}
+ if [ "$detected_version" = "$dirnm" ]; then
+ detected_version="unknown"
+ fi
+fi
+
+
+echo "Configuring ${pkg_name}-${detected_version}"
+
# Save arguments
cat > config.status <<EOF
#!/bin/sh
@@ -143,6 +158,7 @@ cat > Makefile <<EOF
$generated_comment
SHELL = /bin/sh
VPATH = ${var_srcdir}
+VERSION = ${detected_version}
srcdir = ${var_srcdir}
prefix = ${var_prefix:-/usr/local}
diff --git a/go.mod b/go.mod
@@ -3,7 +3,6 @@ module taler.net/taler-mailbox
go 1.19
require (
- git.gnunet.org/gnunet-go.git v0.1.28-0.20220717050634-369422be2512
github.com/gorilla/mux v1.8.1
github.com/schanzen/taler-go v1.1.0
gopkg.in/ini.v1 v1.67.0
@@ -14,9 +13,6 @@ require (
)
require (
- filippo.io/edwards25519 v1.1.0 // indirect
- github.com/bfix/gospel v1.2.31 // indirect
- github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
diff --git a/go.sum b/go.sum
@@ -1,13 +1,5 @@
-filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
-filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
-git.gnunet.org/gnunet-go.git v0.1.28-0.20220717050634-369422be2512 h1:RHHLRqEzdblfKOx/isc6E/0/6bJfWLgwWVAXNX5dI7A=
-git.gnunet.org/gnunet-go.git v0.1.28-0.20220717050634-369422be2512/go.mod h1:dfSzJbX7Hc7tywZT498/WgTEzoXWZnuvKH6JSFjbyME=
-github.com/bfix/gospel v1.2.31 h1:14ymN2Fo7aTYiJ0HEhL0jMg+ofe97HwTHvkntj0DutE=
-github.com/bfix/gospel v1.2.31/go.mod h1:s1zIBLFzCWoz2khLuNgDMtzzXtReGmyWVyGTO7ELkHg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-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/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
diff --git a/internal/util/helper.go b/internal/util/helper.go
@@ -0,0 +1,127 @@
+// This file is part of taldir, the Taler Directory implementation.
+// Copyright (C) 2025 Martin Schanzenbach
+//
+// Taldir is free software: you can redistribute it and/or modify it
+// under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// Taldir 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
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+package util
+
+import (
+ "errors"
+ "strings"
+)
+
+//------------------------------------------------------------------------
+// Base32 conversion between binary data and string representation
+//------------------------------------------------------------------------
+//
+// A binary array of size m is viewed as a consecutive stream of bits
+// from left to right. Bytes are ordered with ascending address, while
+// bits (in a byte) are ordered MSB to LSB.
+
+// For encoding the stream is partitioned into 5-bit chunks; the last chunk
+// is right-padded with 0's if 8*m is not divisible by 5. Each chunk (value
+// between 0 and 31) is encoded into a character; the mapping for encoding
+// is the same as in [https://www.crockford.com/wrmg/base32.html].
+//
+// For decoding each character is converted to a 5-bit chunk based on the
+// encoder mapping (with one addition: the character 'U' maps to the value
+// 27). The chunks are concatenated to produce the bit stream to be stored
+// in the output array.
+
+// character set used for encoding/decoding
+const xlate = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
+
+var (
+ // ErrInvalidEncoding signals an invalid encoding
+ ErrInvalidEncoding = errors.New("invalid encoding")
+ // ErrBufferTooSmall signalsa too small buffer for decoding
+ ErrBufferTooSmall = errors.New("buffer to small")
+)
+
+// EncodeBinaryToString encodes a byte array into a string.
+func Base32CrockfordEncode(data []byte) string {
+ size, pos, bits, n := len(data), 0, 0, 0
+ out := ""
+ for {
+ if n < 5 {
+ if pos < size {
+ bits = (bits << 8) | (int(data[pos]) & 0xFF)
+ pos++
+ n += 8
+ } else if n > 0 {
+ bits <<= uint(5 - n)
+ n = 5
+ } else {
+ break
+ }
+ }
+ out += string(xlate[(bits>>uint(n-5))&0x1F])
+ n -= 5
+ }
+ return out
+}
+
+// Base32CrockfordDecode decodes a string into a byte array.
+// The function expects the size of the output buffer to be sepcified as an
+// argument ('num'); the function returns an error if the buffer is overrun
+// or if an invalid character is found in the encoded string. If the decoded
+// bit stream is smaller than the output buffer, it is padded with 0's.
+func Base32CrockfordDecode(s string, num int) ([]byte, error) {
+ size := len(s)
+ out := make([]byte, num)
+ rpos, wpos, n, bits := 0, 0, 0, 0
+ for {
+ if n < 8 {
+ if rpos < size {
+ c := rune(s[rpos])
+ rpos++
+ v := strings.IndexRune(xlate, c)
+ if v == -1 {
+ switch c {
+ case 'O':
+ v = 0
+ case 'I', 'L':
+ v = 1
+ case 'U':
+ v = 27
+ default:
+ return nil, ErrInvalidEncoding
+ }
+ }
+ bits = (bits << 5) | (v & 0x1F)
+ n += 5
+ } else {
+ if wpos < num {
+ out[wpos] = byte(bits & ((1 << uint(n+1)) - 1))
+ wpos++
+ for i := wpos; i < num; i++ {
+ out[i] = 0
+ }
+ }
+ break
+ }
+ } else {
+ if wpos < num {
+ out[wpos] = byte((bits >> uint(n-8)) & 0xFF)
+ wpos++
+ n -= 8
+ } else {
+ return nil, ErrBufferTooSmall
+ }
+ }
+ }
+ return out, nil
+}
diff --git a/pkg/rest/mailbox.go b/pkg/rest/mailbox.go
@@ -35,7 +35,6 @@ import (
"strings"
"time"
- gnunetutil "git.gnunet.org/gnunet-go.git/pkg/util"
"github.com/gorilla/mux"
"github.com/schanzen/taler-go/pkg/merchant"
tos "github.com/schanzen/taler-go/pkg/rest"
@@ -44,11 +43,17 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/logger"
"taler.net/taler-mailbox/internal/gana"
+ "taler.net/taler-mailbox/internal/util"
)
type TalerMailboxBoxySize int
type MailboxConfig struct {
+ // libtool-style representation of the Mailbox protocol version, see
+ // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+ // The format is "current:revision:age".
+ LibtoolVersion string
+
// Version
Version string
@@ -96,7 +101,7 @@ type Mailbox struct {
// VersionResponse is the JSON response of the /config endpoint
type VersionResponse struct {
- // libtool-style representation of the Merchant protocol version, see
+ // libtool-style representation of the Mailbox protocol version, see
// https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
// The format is "current:revision:age".
Version string `json:"version"`
@@ -168,7 +173,7 @@ func (m *Mailbox) configResponse(w http.ResponseWriter, r *http.Request) {
}
cfg := VersionResponse{
- Version: m.Cfg.Version,
+ Version: m.Cfg.LibtoolVersion,
Name: "taler-mailbox",
MessageBodyBytes: m.MessageBodyBytes,
MessageResponseLimit: m.MessageResponseLimit,
@@ -239,7 +244,7 @@ func (m *Mailbox) sendMessageResponse(w http.ResponseWriter, r *http.Request) {
// Check if order exists and was paid already.
h := sha256.New()
h.Sum(body)
- orderId := gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ orderId := util.Base32CrockfordEncode(h.Sum(nil))
httpStatus, paymentStatus, payto, paytoErr := m.Merchant.IsOrderPaid(orderId)
if paytoErr != nil {
fmt.Println(paytoErr)
@@ -317,18 +322,18 @@ func (m *Mailbox) deleteMessagesResponse(w http.ResponseWriter, r *http.Request)
http.Error(w, "If-Match contains malformed etag number", 400)
return
}
- pkey, err := gnunetutil.DecodeStringToBinary(vars["mailbox"], 32)
+ pkey, err := util.Base32CrockfordDecode(vars["mailbox"], 32)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- checksum, err := gnunetutil.DecodeStringToBinary(msg.Checksum, 64)
+ checksum, err := util.Base32CrockfordDecode(msg.Checksum, 64)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
pk := ed25519.PublicKey(pkey)
- sig, err := gnunetutil.DecodeStringToBinary(msg.WalletSig, 64)
+ sig, err := util.Base32CrockfordDecode(msg.WalletSig, 64)
if nil != err {
w.WriteHeader(http.StatusBadRequest)
return
@@ -345,7 +350,7 @@ func (m *Mailbox) deleteMessagesResponse(w http.ResponseWriter, r *http.Request)
}
h := sha512.New()
h.Write(pkey)
- h_mailbox := gnunetutil.EncodeBinaryToString(h.Sum(nil))
+ h_mailbox := util.Base32CrockfordEncode(h.Sum(nil))
err = m.Db.Where("h_mailbox = ? AND id >= ?", h_mailbox, etag_expected).Limit(msg.Count).Find(&entries).Error
if err != nil {
w.WriteHeader(http.StatusInternalServerError)