[X2Go-Commits] [libx2goclient] 09/09: src/x2goclient-openssh-version: x2goclient_openssh_version_parse ().
git-admin at x2go.org
git-admin at x2go.org
Sat Apr 4 17:55:27 CEST 2020
This is an automated email from the git hooks/post-receive script.
x2go pushed a commit to branch master
in repository libx2goclient.
commit 19ca40073e7e02d3167f9e01afa2fc506393a92e
Author: Mihai Moldovan <ionic at ionic.de>
Date: Sat Apr 4 17:54:52 2020 +0200
src/x2goclient-openssh-version: x2goclient_openssh_version_parse ().
Parses the OpenSSH version string into a version struct for later use.
---
src/x2goclient-openssh-version.c | 245 +++++++++++++++++++++++++++++++++++++++
src/x2goclient-openssh-version.h | 30 +++++
2 files changed, 275 insertions(+)
diff --git a/src/x2goclient-openssh-version.c b/src/x2goclient-openssh-version.c
index 3ea53db..6fb193a 100644
--- a/src/x2goclient-openssh-version.c
+++ b/src/x2goclient-openssh-version.c
@@ -22,11 +22,15 @@
Boston, MA 02110-1301, USA.
*/
+#include <glib.h>
+#include <glib/gprintf.h>
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "x2goclient-openssh-version.h"
+#include "x2goclient-utils.h"
X2GoClientOpenSSHVersion* x2goclient_openssh_version_new (void) {
return (g_slice_new0 (X2GoClientOpenSSHVersion));
@@ -46,3 +50,244 @@ static X2GoClientOpenSSHVersion* x2goclient_openssh_version_copy (X2GoClientOpen
}
G_DEFINE_BOXED_TYPE (X2GoClientOpenSSHVersion, x2goclient_openssh_version, &x2goclient_openssh_version_copy, &x2goclient_openssh_version_free)
+
+void x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version, const gchar *version_string, GError **gerr) {
+ /* Basic sanity checks on struct and string. */
+ if (!(openssh_version)) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_STRUCT, "No version struct passed, cannot store extracted information.");
+ return;
+ }
+
+ if (!(version_string)) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_VERSION_STRING, "No version string passed, cannot extract information.");
+ return;
+ }
+
+ X2GoClientOpenSSHVersion *struct_work_copy = x2goclient_openssh_version_copy (openssh_version);
+
+ /*
+ * We expect the version string to have a more-or-less fixed format, such as:
+ *
+ * OpenSSH_<major>.<minor>p<patch><additional data>[,<whitespace><end of line>]
+ */
+ /* Start with the fixed preamble. */
+ const gchar *tmp = version_string;
+ if (!(g_str_has_prefix (tmp, "OpenSSH_"))) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_PREAMBLE, "Preamble in version string does not match expected value 'OpenSSH_'.");
+
+ x2goclient_openssh_version_free (struct_work_copy);
+ struct_work_copy = NULL;
+
+ return;
+ }
+
+ /* Skip preamble, scan for major version number separator (dot). */
+ tmp += 8;
+ const gchar *dot_search = g_strstr_len (tmp, -1, ".");
+ if (!(dot_search)) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_NO_MAJOR_SEPARATOR, "Version string does not contain major version number separator.");
+
+ x2goclient_openssh_version_free (struct_work_copy);
+ struct_work_copy = NULL;
+
+ return;
+ }
+
+ g_assert (tmp < dot_search);
+
+ /* Sanity check on major version number - must be numeric/all digits. */
+ const gchar *int_search = NULL;
+ for (int_search = tmp; int_search < dot_search; ++int_search) {
+ if (!(g_ascii_isdigit (*int_search))) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_NOT_NUMERIC, "Major version number is not numeric.");
+
+ x2goclient_openssh_version_free (struct_work_copy);
+ struct_work_copy = NULL;
+
+ return;
+ }
+ }
+
+ /* Copy and convert major version number. */
+ gchar *tmp_copy = g_strndup (tmp, dot_search - tmp);
+ struct_work_copy->major = -1;
+
+ _Bool conv_err = TRUE,
+ min_err = TRUE,
+ max_err = TRUE;
+ const gchar *end = NULL;
+ long long conv = x2goclient_str_to_int (tmp_copy, TRUE, 0, TRUE, G_MAXUINT32, &end, &conv_err, &min_err, &max_err);
+
+ if (conv_err) {
+ if (min_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_UNDERFLOW, "Major version number is too small to fit into long long type.");
+ }
+ else if (max_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_OVERFLOW, "Major version number is too big to fit into long long type.");
+ }
+ else {
+ end = NULL;
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_NOT_NUMERIC, "Major version number is not numeric.");
+ }
+ }
+ else {
+ if (min_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_NEGATIVE, "Major version number is not numeric.");
+ }
+ else if (max_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_TOO_BIG, "Major version number is too big.");
+ }
+ else {
+ struct_work_copy->major = conv;
+ }
+ }
+
+ if (end) {
+ /* Map end pointer to original string. */
+ tmp += (end - tmp_copy);
+ }
+
+ g_free (tmp_copy);
+ tmp_copy = NULL;
+
+ if (0 > struct_work_copy->major) {
+ x2goclient_openssh_version_free (struct_work_copy);
+ struct_work_copy = NULL;
+
+ return;
+ }
+
+ /* Copy and convert minor version number. */
+ tmp_copy = g_strdup (tmp);
+ struct_work_copy->minor = -1;
+
+ conv_err = min_err = max_err = TRUE;
+ end = NULL;
+ conv = x2goclient_str_to_int (tmp_copy, TRUE, 0, TRUE, G_MAXUINT32, &end, &conv_err, &min_err, &max_err);
+
+ if (conv_err) {
+ if (min_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_UNDERFLOW, "Minor version number is too small to fit into long long type.");
+ }
+ else if (max_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_OVERFLOW, "Minor version number is too big to fit into long long type.");
+ }
+ else {
+ end = NULL;
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_NOT_NUMERIC, "Minor version number is not numeric.");
+ }
+ }
+ else {
+ if (min_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_NEGATIVE, "Minor version number is not numeric.");
+ }
+ else if (max_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_TOO_BIG, "Minor version number is too big.");
+ }
+ else {
+ struct_work_copy->minor = conv;
+ }
+ }
+
+ if (end) {
+ /* Map end pointer to original string. */
+ tmp += (end - tmp_copy);
+ }
+
+ g_free (tmp_copy);
+ tmp_copy = NULL;
+
+ /*
+ * Handle error and additionally scan for the next character which MUST be a
+ * 'p' according to our scheme.
+ */
+ if ((0 > struct_work_copy->minor) || ('p' != *tmp)) {
+ x2goclient_openssh_version_free (struct_work_copy);
+ struct_work_copy = NULL;
+
+ return;
+ }
+ else {
+ /* Skip 'p' character. */
+ ++tmp;
+ }
+
+ /* Copy and convert patch version number. */
+ tmp_copy = g_strdup (tmp);
+ struct_work_copy->patch = -1;
+
+ conv_err = min_err = max_err = TRUE;
+ end = NULL;
+ conv = x2goclient_str_to_int (tmp_copy, TRUE, 0, TRUE, G_MAXUINT32, &end, &conv_err, &min_err, &max_err);
+
+ if (conv_err) {
+ if (min_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_UNDERFLOW, "Patch version number is too small to fit into long long type.");
+ }
+ else if (max_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_OVERFLOW, "Patch version number is too big to fit into long long type.");
+ }
+ else {
+ end = NULL;
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_NOT_NUMERIC, "Patch version number is not numeric.");
+ }
+ }
+ else {
+ if (min_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_NEGATIVE, "Patch version number is not numeric.");
+ }
+ else if (max_err) {
+ g_set_error_literal (gerr, X2GOCLIENT_OPENSSH_VERSION_ERROR, X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_TOO_BIG, "Patch version number is too big.");
+ }
+ else {
+ struct_work_copy->patch = conv;
+ }
+ }
+
+ if (end) {
+ /* Map end pointer to original string. */
+ tmp += (end - tmp_copy);
+ }
+
+ g_free (tmp_copy);
+ tmp_copy = NULL;
+
+ if (0 > struct_work_copy->patch) {
+ x2goclient_openssh_version_free (struct_work_copy);
+ struct_work_copy = NULL;
+
+ return;
+ }
+
+ /* Scan for a comma which should follow any additional version data. */
+ end = g_strstr_len (tmp, -1, ",");
+ if (!(end)) {
+ /*
+ * Alternatively, scan for whitespace and we'll treat that as the
+ * additional version data separator.
+ */
+ end = g_strstr_len (tmp, -1, " \t");
+
+ if (!(end)) {
+ /*
+ * No separator means or trailing whitespace means that we'll have to
+ * fast-forward to the actual end.
+ */
+ end = (tmp + (strlen (tmp)));
+ }
+ }
+
+ if ((end) && (0 < (end - tmp))) {
+ /* If we have additional data, copy it. */
+ g_strlcpy (struct_work_copy->addon, tmp, (end - tmp));
+ }
+
+ /* Not having additional data is not an error. */
+
+ /* Copy the struct. */
+ *openssh_version = *struct_work_copy;
+
+ /* Lastly, free data. */
+ x2goclient_openssh_version_free (struct_work_copy);
+ struct_work_copy = NULL;
+}
diff --git a/src/x2goclient-openssh-version.h b/src/x2goclient-openssh-version.h
index af6aebe..fcb5f83 100644
--- a/src/x2goclient-openssh-version.h
+++ b/src/x2goclient-openssh-version.h
@@ -45,6 +45,36 @@ GType x2goclient_openssh_version_get_type (void) G_GNUC_CONST;
X2GoClientOpenSSHVersion* x2goclient_openssh_version_new (void);
void x2goclient_openssh_version_free (X2GoClientOpenSSHVersion *openssh_version);
+/*
+ * Error handling helpers.
+ */
+#define X2GOCLIENT_OPENSSH_VERSION_ERROR g_quark_from_static_string ("x2goclient-openssh-version")
+
+enum {
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_STRUCT = 0,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_VERSION_STRING,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_PREAMBLE,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_NO_MAJOR_SEPARATOR,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_NOT_NUMERIC,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_UNDERFLOW,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_OVERFLOW,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_TOO_BIG,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MAJOR_NEGATIVE,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_NOT_NUMERIC,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_UNDERFLOW,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_OVERFLOW,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_TOO_BIG,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_MINOR_NEGATIVE,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_NOT_NUMERIC,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_UNDERFLOW,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_OVERFLOW,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_TOO_BIG,
+ X2GOCLIENT_OPENSSH_VERSION_ERROR_PATCH_NEGATIVE,
+};
+
+
+void x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version, const gchar *version_string, GError **gerr);
+
G_END_DECLS
#endif /* x2goclient_openssh_version_h */
--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/libx2goclient.git
More information about the x2go-commits
mailing list