github.com/ethanhsieh/snapd@v0.0.0-20210615102523-3db9b8e4edc5/snapdenv/useragent.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016-2020 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package snapdenv
    21  
    22  import (
    23  	"fmt"
    24  	"strings"
    25  
    26  	"github.com/snapcore/snapd/arch"
    27  	"github.com/snapcore/snapd/osutil"
    28  	"github.com/snapcore/snapd/release"
    29  )
    30  
    31  // UserAgent to send
    32  var userAgent = "unset"
    33  
    34  // SetUserAgentFromVersion sets up a user-agent string.
    35  func SetUserAgentFromVersion(version string, probeForceDevMode func() bool, extraProds ...string) (restore func()) {
    36  	extras := make([]string, 1, 3)
    37  	extras[0] = "series " + release.Series
    38  	if release.OnClassic {
    39  		extras = append(extras, "classic")
    40  	}
    41  	if probeForceDevMode != nil && probeForceDevMode() {
    42  		extras = append(extras, "devmode")
    43  	}
    44  	if Testing() {
    45  		extras = append(extras, "testing")
    46  	}
    47  	extraProdStr := ""
    48  	if len(extraProds) != 0 {
    49  		extraProdStr = " " + strings.Join(extraProds, " ")
    50  	}
    51  	origUserAgent := userAgent
    52  
    53  	// xxx this assumes ReleaseInfo's ID and VersionID don't have weird characters
    54  	// (see rfc 7231 for values of weird)
    55  	// assumption checks out in practice, q.v. https://github.com/zyga/os-release-zoo
    56  	userAgent = fmt.Sprintf("snapd/%v (%s)%s %s/%s (%s) linux/%s", version,
    57  		strings.Join(extras, "; "), extraProdStr, release.ReleaseInfo.ID,
    58  		release.ReleaseInfo.VersionID, string(arch.DpkgArchitecture()),
    59  		sanitizeKernelVersion(osutil.KernelVersion()))
    60  	return func() {
    61  		userAgent = origUserAgent
    62  	}
    63  }
    64  
    65  func sanitizeKernelVersion(in string) string {
    66  	out := stripUnsafeRunes(in)
    67  	// Arbitrary choice, limit kernel version to 25 characters
    68  	if len(out) > 25 {
    69  		out = out[:25]
    70  	}
    71  	return out
    72  }
    73  
    74  func safeRuneMapper(r rune) rune {
    75  	if r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' || r == '-' || r == '_' || r == '.' {
    76  		return r
    77  	}
    78  	return -1
    79  }
    80  
    81  func stripUnsafeRunes(in string) string {
    82  	return strings.Map(safeRuneMapper, in)
    83  }
    84  
    85  // UserAgent returns the user-agent string setup through SetUserAgentFromVersion.
    86  func UserAgent() string {
    87  	return userAgent
    88  }