gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet-go-plugins] branch master updated: reclaimid: initial revision.


From: gnunet
Subject: [gnunet-go-plugins] branch master updated: reclaimid: initial revision.
Date: Thu, 03 Nov 2022 15:00:01 +0100

This is an automated email from the git hooks/post-receive script.

bernd-fix pushed a commit to branch master
in repository gnunet-go-plugins.

The following commit(s) were added to refs/heads/master by this push:
     new 6f1282c  reclaimid: initial revision.
6f1282c is described below

commit 6f1282c4d1910fde3100c2f24cf38a344662c314
Author: Bernd Fix <brf@hoi-polloi.org>
AuthorDate: Thu Nov 3 13:17:23 2022 +0100

    reclaimid: initial revision.
---
 reclaimid/Makefile       |  33 ++++++++
 reclaimid/gui.htpl       | 111 ++++++++++++++++++++++++
 reclaimid/main.go        | 146 ++++++++++++++++++++++++++++++++
 reclaimid/plugin_test.go | 119 ++++++++++++++++++++++++++
 reclaimid/records.go     | 215 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 624 insertions(+)

diff --git a/reclaimid/Makefile b/reclaimid/Makefile
new file mode 100644
index 0000000..0f52007
--- /dev/null
+++ b/reclaimid/Makefile
@@ -0,0 +1,33 @@
+# This file is part of gnunet-go-plugins, a collection of plugins for
+# the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+# implement type-specific processing of resource records (e.g. GUI).
+# Copyright (C) 2022 by the authors:
+#
+# * Bernd Fix <brf@hoi-polloi.org>  >Y<
+#
+# gnunet-go-plugins 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.
+#
+# gnunet-go 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
+
+
+all: ${GOPATH}/bin/plugin_reclaimid.so
+
+clean:
+       rm -f ${GOPATH}/bin/plugin_reclaimid.so
+
+test:
+       go test -v ./...
+
+${GOPATH}/bin/plugin_reclaimid.so: main.go records.go gui.htpl
+       go build -buildmode=plugin -trimpath -gcflags="-N -l" -o $@ ./...
diff --git a/reclaimid/gui.htpl b/reclaimid/gui.htpl
new file mode 100644
index 0000000..8317a72
--- /dev/null
+++ b/reclaimid/gui.htpl
@@ -0,0 +1,111 @@
+{{define "new_myrecords"}}
+    <!-- DEBUG: show template parameters -->
+    <div>
+        <h3>Template data:</h3>
+       <p>Ref = {{.Ref}}</p>
+           <p>Action = {{.Action}}</p>
+           <p>Button = {{.Button}}</p>
+        <p>Names: {{range $i,$v := .Names}}'{{$v}}',{{end}}</p>
+        <p>RRSpecs:</p>
+        <ul>
+            {{range $i,$s := .RRspecs}}
+            <li>Type = {{$s.Type}}, Flags = {{$s.Flags}}</li>
+            {{end}}
+        </ul>
+        <p>Params:</p>
+        <ul>
+        {{range $k,$v := .Params}}
+            <li>'{{$k}}' = '{{$v}}'</li>
+        {{end}}
+        </ul>
+    </div>
+
+    {{$data := .}}
+    <div>
+        <h3>Creating a new custom resource record for label "{{index .Params 
"label"}}":</h3>
+        <div class="tabset">
+            {{range $i, $type := .RRspecs}}
+            <input type="radio" name="tabset" id="tab{{$i}}" 
aria-controls="tab{{$i}}" {{if eq $i 0}}checked{{end}}>
+            <label for="tab{{$i}}">{{rrtype $type.Type}}</label>
+            {{end}}
+            <div class="tab-panels">
+                {{range $i, $spec := .RRspecs}}
+                <section id="tab{{$i}}" class="tab-panel">
+                    {{$t := rrtype $spec.Type}}
+                    {{$pf := setspecs $data.Params $spec}}
+                    {{if eq $t "MYRECTYPE1"}}{{template "MYRECTYPE1" 
$data}}{{end}}
+                    {{if eq $t "MYRECTYPE2"}}{{template "MYRECTYPE2" 
$data}}{{end}}
+                </section>
+                {{end}}
+            </div>
+        </div>
+        <a href="/"><button>Leave</button></a>
+    </div>
+{{end}}
+
+{{define "edit_myrecords"}}
+    <!-- DEBUG: show template parameters -->
+    <div>
+        <h3>Template data:</h3>
+       <p>Ref = {{.Ref}}</p>
+           <p>Action = {{.Action}}</p>
+           <p>Button = {{.Button}}</p>
+        <p>Names: {{range $i,$v := .Names}}'{{$v}}',{{end}}</p>
+        <ul>
+        {{range $k,$v := .Params}}
+            <li>'{{$k}}' = '{{$v}}'</li>
+        {{end}}
+        </ul>
+    </div>
+
+    <div>
+        <h3>Edit a resource record for label {{index .Params "label"}}:</h3>
+        <p><small>(Created: {{index .Params "created"}}, Last edited: {{index 
.Params "modified"}})</small></p>
+        {{$t := rritype (index .Params "type")}}
+        {{if eq $t "MYRECTYPE1"}}{{template "MYRECTYPE1" .}}{{end}}
+        {{if eq $t "MYRECTYPE2"}}{{template "MYRECTYPE2" .}}{{end}}
+    </div>
+    <a href="/"><button>Leave</button></a>
+{{end}}
+
+{{define "MYRECTYPE1"}}
+    <h3>RECTYPE1</h3>
+    <form action="/action/{{.Action}}/rr/{{.Ref}}" {{if eq .Action 
"upd"}}method="post"{{end}}>
+        <input type="hidden" name="type" value="{{index .Params "type"}}">
+        <table>
+            <tr>
+                <td align="right"><b>Attribute1:</b></td>
+                <td>
+                    <input type="text" name="myrec1_text"
+                        maxlength="63" size="63"
+                        autofocus required
+                        value="{{index .Params "myrec1_text"}}"
+                    >
+                </td>
+            </tr>
+            {{template "RRCommon" .}}
+            <tr><td/><td><button id="submit">{{.Button}} 
record</button></td></tr>
+        </table>
+    </form>
+{{end}}
+
+{{define "MYRECTYPE2"}}
+    <h3>RECTYPE2</h3>
+    <form action="/action/{{.Action}}/rr/{{.Ref}}" {{if eq .Action 
"upd"}}method="post"{{end}}>
+        <input type="hidden" name="type" value="{{index .Params "type"}}">
+        <table>
+            <tr>
+                <td align="right"><b>Attribute1:</b></td>
+                <td>
+                    <input type="text" name="myrec2_text"
+                        maxlength="63" size="63"
+                        autofocus required
+                        value="{{index .Params "myrec2_text"}}"
+                    >
+                </td>
+            </tr>
+            {{template "RRCommon" .}}
+            <tr><td/><td><button id="submit">{{.Button}} 
record</button></td></tr>
+        </table>
+    </form>
+{{end}}
diff --git a/reclaimid/main.go b/reclaimid/main.go
new file mode 100644
index 0000000..fc24ecd
--- /dev/null
+++ b/reclaimid/main.go
@@ -0,0 +1,146 @@
+// This file is part of gnunet-go-plugins, a collection of plugins for
+// the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+// implement type-specific processing of resource records (e.g. GUI).
+// Copyright (C) 2022 by the authors:
+//
+// * Bernd Fix <brf@hoi-polloi.org>  >Y<
+//
+// gnunet-go-plugins 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.
+//
+// gnunet-go 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 main
+
+import (
+       _ "embed"
+
+       "github.com/bfix/gospel/data"
+)
+
+//======================================================================
+//   C U S T O M I Z A T I O N
+//======================================================================
+
+// List of handled resource record types.
+var handledTypes = []uint32{
+       65544, // RECLAIM_ATTRIBUTE
+       65545, // RECLAIM_TICKET
+       65550, // RECLAIM_ATTRIBUTE_REF
+       65552, // RECLAIM_OIDC_CLIENT
+       65553, // RECLAIM_OIDC_REDIRECT
+       65554, // RECLAIM_CREDENTIAL
+       65555, // RECLAIM_PRESENTATION
+}
+
+//----------------------------------------------------------------------
+// Interface implementation
+//----------------------------------------------------------------------
+
+// Name returns the plugin name (sub-system name)
+func (p *CustomPlugin) Name() string {
+       return "Re:claimID"
+}
+
+// CanHandle returns a list of resource record types that are handled
+// by the plugin.
+func (p *CustomPlugin) CanHandle() (list []uint32) {
+       return handledTypes
+}
+
+// Compute a set of record specs allowed under a label with existing records
+func (p *CustomPlugin) Compatible(_ string, _ [][2]uint32) [][2]uint32 {
+       // simple case: no restrictions (all types, all flags)
+       list := make([][2]uint32, 0)
+       for _, t := range handledTypes {
+               list = append(list, [2]uint32{t, 0})
+       }
+       return list
+}
+
+// TemplateNames returns the names of the new / edit template
+// TODO: customize template names (see gui.htpl)
+func (p *CustomPlugin) TemplateNames() (string, string) {
+       return "new_reclaimid", "edit_reclaimid"
+}
+
+// Prefix returns the prefix for record attributes in map
+func (p *CustomPlugin) Prefix(t uint32) string {
+       switch t {
+       case 65544: // RECLAIM_ATTRIBUTE
+               return "reclaimid_attr"
+       case 65545: // RECLAIM_TICKET
+       case 65550: // RECLAIM_ATTRIBUTE_REF
+       case 65552: // RECLAIM_OIDC_CLIENT
+       case 65553: // RECLAIM_OIDC_REDIRECT
+       case 65554: // RECLAIM_CREDENTIAL
+       case 65555: // RECLAIM_PRESENTATION
+       }
+       return "unknown"
+}
+
+//======================================================================
+// No need to customize code beond this point...
+//======================================================================
+
+// Plugin is the instance of a custom implementation accessed by the
+// gnunet-go framework
+var Plugin = NewCustomPlugin()
+
+// ExamplePlugin is an example plugin for custom records that implements
+// the zonemaster.Plugin interface.
+type CustomPlugin struct{}
+
+// NewCustomPlugin creates an initialized plugin instance
+func NewCustomPlugin() CustomPlugin {
+       return CustomPlugin{}
+}
+
+//go:embed gui.htpl
+var tpl []byte
+
+// Template returns the new / edit template for resource record types
+// handled by the plugin.
+func (p *CustomPlugin) Template() string {
+       return string(tpl)
+}
+
+// Value returns a human-readable description of RR data
+func (p *CustomPlugin) Value(t uint32, rr []byte) (string, error) {
+       rec, err := GetInstance(t, rr)
+       if err != nil {
+               return "", err
+       }
+       return rec.Value()
+}
+
+// ToMap converts resource record data into GUI template variables
+func (p *CustomPlugin) ToMap(t uint32, rr []byte) (map[string]string, error) {
+       rec, err := GetInstance(t, rr)
+       if err != nil {
+               return nil, err
+       }
+       return rec.ToMap()
+}
+
+// FromMap converts a GUI template variables into resource record data
+func (p *CustomPlugin) FromMap(t uint32, vars map[string]string) ([]byte, 
error) {
+       rec, err := GetInstance(t, nil)
+       if err != nil {
+               return nil, err
+       }
+       if err = rec.FromMap(vars); err != nil {
+               return nil, err
+       }
+       return data.Marshal(rec)
+}
diff --git a/reclaimid/plugin_test.go b/reclaimid/plugin_test.go
new file mode 100644
index 0000000..2a4f2fa
--- /dev/null
+++ b/reclaimid/plugin_test.go
@@ -0,0 +1,119 @@
+// This file is part of gnunet-go-plugins, a collection of plugins for
+// the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+// implement type-specific processing of resource records (e.g. GUI).
+// Copyright (C) 2022 by the authors:
+//
+// * Bernd Fix <brf@hoi-polloi.org>  >Y<
+//
+// gnunet-go-plugins 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.
+//
+// gnunet-go 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 main
+
+import (
+       "testing"
+)
+
+func TestPluginCanHandle(t *testing.T) {
+       list := Plugin.CanHandle()
+       if len(list) == 0 {
+               t.Fatal("no type list received from plugin")
+       }
+       for _, rr := range list {
+               t.Logf("Can handle %d\n", rr)
+       }
+}
+
+func TestPluginCompatible(t *testing.T) {
+       in := make([][2]uint32, 0)
+       out := Plugin.Compatible("@", in)
+       for _, s := range out {
+               t.Logf("Compatible: type=%d, flags=%d\n", s[0], s[1])
+       }
+}
+
+func TestPluginPrefix(t *testing.T) {
+       for _, rr := range Plugin.CanHandle() {
+               t.Logf("Prefix: '%s' (%d)\n", Plugin.Prefix(rr), rr)
+       }
+}
+
+var (
+       recAttr = []byte{
+               0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x9a, 0x97, 0xbc, 0x98, 0x67, 0x57, 0x3d, 0x65,
+               0x9e, 0x9d, 0x08, 0x62, 0x7a, 0xd3, 0xe3, 0xb9,
+               0xb2, 0xe1, 0xce, 0x7e, 0xb8, 0xed, 0x3b, 0x8d,
+               0x46, 0xd8, 0xe3, 0xdb, 0xe8, 0xbb, 0x45, 0x8b,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
+               0x65, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x72, 0x66,
+               0x40, 0x68, 0x6f, 0x69, 0x2d, 0x70, 0x6f, 0x6c,
+               0x6c, 0x6f, 0x69, 0x2e, 0x6f, 0x72, 0x67, 0x00,
+       }
+)
+
+func TestPluginValueAttribute(t *testing.T) {
+       s, err := Plugin.Value(65544, recAttr)
+       if err != nil {
+               t.Fatal(err)
+       }
+       t.Logf("attribute: value='%s'\n", s)
+}
+
+func TestPluginToMap(t *testing.T) {
+       /*
+               params, err := Plugin.ToMap(90666, rec1)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               t.Logf("ToMap: rec1 -> %v\n", params)
+
+               if params, err = Plugin.ToMap(90667, rec2); err != nil {
+                       t.Fatal(err)
+               }
+               t.Logf("ToMap: rec2 -> %v\n", params)
+       */
+}
+
+func TestPluginFromMap(t *testing.T) {
+       /*
+               params := map[string]string{
+                       "rectype1_text": "foo",
+               }
+               rr, err := Plugin.FromMap(90666, params)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               t.Logf("FromMap: rr=%s\n", hex.EncodeToString(rr))
+               if !bytes.Equal(rr, rec1) {
+                       t.Fatal("FromMap for rectype1 failed")
+               }
+               params = map[string]string{
+                       "rectype2_var1": "35",
+                       "rectype2_var2": "66",
+               }
+               if rr, err = Plugin.FromMap(90667, params); err != nil {
+                       t.Fatal(err)
+               }
+               t.Logf("FromMap: rr=%s\n", hex.EncodeToString(rr))
+               if !bytes.Equal(rr, rec2) {
+                       t.Fatal("FromMap for rectype2 failed")
+               }
+       */
+}
diff --git a/reclaimid/records.go b/reclaimid/records.go
new file mode 100644
index 0000000..6886b31
--- /dev/null
+++ b/reclaimid/records.go
@@ -0,0 +1,215 @@
+// This file is part of gnunet-go-plugins, a collection of plugins for
+// the GNUnet-implementation in Golang (gnunet.go). Plugins are used to
+// implement type-specific processing of resource records (e.g. GUI).
+// Copyright (C) 2022 by the authors:
+//
+// * Bernd Fix <brf@hoi-polloi.org>  >Y<
+//
+// gnunet-go-plugins 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.
+//
+// gnunet-go 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 main
+
+import (
+       "bytes"
+       "encoding/base32"
+       "encoding/hex"
+       "fmt"
+       "strconv"
+       "strings"
+
+       "github.com/bfix/gospel/data"
+)
+
+// ReclaimRecord interface impemented by custom types.
+type ReclaimRecord interface {
+       Value() (string, error)
+       ToMap() (map[string]string, error)
+       FromMap(map[string]string) error
+}
+
+// Get record instance for given type and data
+func GetInstance(t uint32, buf []byte) (rec ReclaimRecord, err error) {
+       switch t {
+       case 65544: // RECLAIM_ATTRIBUTE
+               rec = new(ReclaimAttribute)
+       case 65545: // RECLAIM_TICKET
+       case 65550: // RECLAIM_ATTRIBUTE_REF
+       case 65552: // RECLAIM_OIDC_CLIENT
+       case 65553: // RECLAIM_OIDC_REDIRECT
+       case 65554: // RECLAIM_CREDENTIAL
+               rec = new(ReclaimCredential)
+       case 65555: // RECLAIM_PRESENTATION
+       }
+       if buf != nil {
+               err = data.Unmarshal(rec, buf)
+       }
+       return
+}
+
+//======================================================================
+// Reclaim Resource Records
+//======================================================================
+
+//----------------------------------------------------------------------
+// Reclaim Attribute
+//----------------------------------------------------------------------
+
+// ReclaimAttribute record
+type ReclaimAttribute struct {
+       Type       uint32 `order:"big"`    // type
+       Flags      uint32 `order:"big"`    // claim
+       ID         []byte `size:"32"`      // Reclaim identifier
+       Credential []byte `size:"32"`      // Reclaim identifier
+       NameLen    uint16 `order:"big"`    // length of name
+       Res1       uint16 `order:"big"`    // reserved
+       DataLen    uint16 `order:"big"`    // length of data
+       Res2       uint16 `order:"big"`    // reserved
+       Name       []byte `size:"NameLen"` // name
+       Data       []byte `size:"DataLen"` // binary data
+}
+
+// Value returns a human-readable representation of the record
+func (rec *ReclaimAttribute) Value() (string, error) {
+       wrt := new(bytes.Buffer)
+       wrt.WriteString(fmt.Sprintf("ID=%s,<br>", encodeBase32GNS(rec.ID)))
+       cred := encodeBase32GNS(rec.Credential)
+       if len(strings.ReplaceAll(cred, "0", "")) > 0 {
+               wrt.WriteString(fmt.Sprintf("Credential=%s,<br>", cred))
+       }
+       wrt.WriteString(fmt.Sprintf("Type=%d,<br>", rec.Type))
+       wrt.WriteString(fmt.Sprintf("Flags=%d,<br>", rec.Flags))
+       name := string(rec.Name)
+       val := string(rec.Data)[:rec.DataLen-1]
+       wrt.WriteString(fmt.Sprintf("[%s=%s]", name, val))
+       return wrt.String(), nil
+}
+
+// ToMap returns the parameter set for the record
+func (rec *ReclaimAttribute) ToMap() (params map[string]string, err error) {
+       params = make(map[string]string)
+       params["reclaim_attribute_id"] = encodeBase32GNS(rec.ID)
+       params["reclaim_attribute_credential"] = encodeBase32GNS(rec.Credential)
+       params["reclaim_attribute_type"] = fmt.Sprintf("%d", rec.Type)
+       params["reclaim_attribute_flags"] = fmt.Sprintf("%d", rec.Flags)
+       params["reclaim_attribute_key"] = string(rec.Name)
+       params["reclaim_attribute_value"] = string(rec.Data)[:rec.DataLen-1]
+       return
+}
+
+// FromMap reconstructs the record attributes from parameter list
+func (rec *ReclaimAttribute) FromMap(params map[string]string) error {
+       return nil
+}
+
+//----------------------------------------------------------------------
+// Reclaim Credential
+//----------------------------------------------------------------------
+
+// ReclaimCredential is a credential resource record data
+type ReclaimCredential struct {
+       Type    uint32 `order:"big"`    // credendial type
+       Flags   uint32 `order:"big"`    // flags
+       ID      []byte `size:"32"`      // credential ID
+       NameLen uint16 `order:"big"`    // length of name
+       Res1    uint16 `order:"big"`    // reserved
+       DataLen uint16 `order:"big"`    // length of data
+       Res2    uint16 `order:"big"`    // reserved
+       Name    []byte `size:"NameLen"` // name
+       Data    []byte `size:"DataLen"` // binary data
+}
+
+// Value returns a human-readable representation of the record
+//
+//nolint:unparam // error-free
+func (rec *ReclaimCredential) Value() (string, error) {
+       wrt := new(bytes.Buffer)
+       wrt.WriteString(fmt.Sprintf("ID=%s,<br>", encodeBase32GNS(rec.ID)))
+       wrt.WriteString(fmt.Sprintf("Type=%d,<br>", rec.Type))
+       wrt.WriteString(fmt.Sprintf("Flags=%d,<br>", rec.Flags))
+       name := string(rec.Name)
+       val := hex.EncodeToString(rec.Data)
+       wrt.WriteString(fmt.Sprintf("[%s=%s]", name, split(val, 64)))
+       return wrt.String(), nil
+}
+
+// ToMap returns the parameter set for the record
+//
+//nolint:unparam // error-free
+func (rec *ReclaimCredential) ToMap() (params map[string]string, err error) {
+       params = make(map[string]string)
+       params["reclaim_credential_id"] = encodeBase32GNS(rec.ID)
+       params["reclaim_credential_type"] = fmt.Sprintf("%d", rec.Type)
+       params["reclaim_credential_flags"] = fmt.Sprintf("%d", rec.Flags)
+       params["reclaim_credential_key"] = string(rec.Name)
+       params["reclaim_credential_value"] = hex.EncodeToString(rec.Data)
+       return
+}
+
+// FromMap reconstructs the record attributes from parameter list
+func (rec *ReclaimCredential) FromMap(params map[string]string) error {
+       return nil
+}
+
+//----------------------------------------------------------------------
+// Helpers
+//----------------------------------------------------------------------
+
+// Split a string into lines of given length
+func split(s string, chunk int) string {
+       out := ""
+       for len(s) > chunk {
+               if len(out) > 0 {
+                       out += ",<br>"
+               }
+               out += s[:chunk]
+               s = s[chunk:]
+       }
+       return out
+}
+
+// Base32GNS encoding character set
+var cf32Enc = base32.NewEncoding("0123456789ABCDEFGHJKMNPQRSTVWXYZ")
+
+// Return a byte array encoded with Base32GNS
+func encodeBase32GNS(buf []byte) string {
+       return strings.TrimRight(cf32Enc.EncodeToString(buf), "=")
+}
+
+// Convert string to byte array using Base32GNS
+func decodeBase32GNS(s string) ([]byte, error) {
+       s = strings.ToUpper(s)
+       s = strings.NewReplacer("O", "0", "I", "1", "L", "1", "U", 
"V").Replace(s)
+       return cf32Enc.DecodeString(s)
+}
+
+// Numbers convertable from parameter value (string)
+type Number interface {
+       uint16 | uint32 | int | int16 | int32 | float32 | float64
+}
+
+// convert parameter value (string) to given number type
+func asInt[T Number](params map[string]string, key string) (val T, err error) {
+       vs, ok := params[key]
+       if !ok {
+               err = fmt.Errorf("%s missing", key)
+               return
+       }
+       var v int
+       if v, err = strconv.Atoi(vs); err != nil {
+               return
+       }
+       return T(v), nil
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]