Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package zypp-boot-plugin for openSUSE:Factory checked in at 2024-07-14 08:48:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/zypp-boot-plugin (Old) and /work/SRC/openSUSE:Factory/.zypp-boot-plugin.new.17339 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "zypp-boot-plugin" Sun Jul 14 08:48:54 2024 rev:6 rq:1186810 version:0.0.11 Changes: -------- --- /work/SRC/openSUSE:Factory/zypp-boot-plugin/zypp-boot-plugin.changes 2024-06-17 19:27:30.685901192 +0200 +++ /work/SRC/openSUSE:Factory/.zypp-boot-plugin.new.17339/zypp-boot-plugin.changes 2024-07-14 08:49:26.926133519 +0200 @@ -1,0 +2,6 @@ +Thu Jul 11 09:32:43 UTC 2024 - sch...@suse.com + +- Update to version 0.0.11: + * Handle content-length of stomp in zypper plugin (bsc#1227418). + +------------------------------------------------------------------- Old: ---- zypp-boot-plugin-0.0.10.tar.xz New: ---- zypp-boot-plugin-0.0.11.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ zypp-boot-plugin.spec ++++++ --- /var/tmp/diff_new_pack.0piKrz/_old 2024-07-14 08:49:28.210180485 +0200 +++ /var/tmp/diff_new_pack.0piKrz/_new 2024-07-14 08:49:28.210180485 +0200 @@ -17,7 +17,7 @@ Name: zypp-boot-plugin -Version: 0.0.10 +Version: 0.0.11 Release: 0 Summary: Zypp plugin for checking if a reboot is needed License: AGPL-3.0-or-later ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.0piKrz/_old 2024-07-14 08:49:28.250181948 +0200 +++ /var/tmp/diff_new_pack.0piKrz/_new 2024-07-14 08:49:28.254182094 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/openSUSE/zypp-boot-plugin.git</param> - <param name="changesrevision">98cb017c70f60681ed3cf0bcb646665d55246078</param></service></servicedata> + <param name="changesrevision">7b39e6110e00d752a03cecbb29a76c47dcdb0047</param></service></servicedata> (No newline at EOF) ++++++ zypp-boot-plugin-0.0.10.tar.xz -> zypp-boot-plugin-0.0.11.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zypp-boot-plugin-0.0.10/NEWS new/zypp-boot-plugin-0.0.11/NEWS --- old/zypp-boot-plugin-0.0.10/NEWS 2024-06-14 11:37:29.000000000 +0200 +++ new/zypp-boot-plugin-0.0.11/NEWS 2024-07-11 11:23:47.000000000 +0200 @@ -1,3 +1,6 @@ +Version 0.0.11 +* Handle content-length of stomp in zypper plugin + Version 0.0.10 * Updated zypp-boot-plugin.conf docu. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zypp-boot-plugin-0.0.10/meson.build new/zypp-boot-plugin-0.0.11/meson.build --- old/zypp-boot-plugin-0.0.10/meson.build 2024-06-14 11:37:29.000000000 +0200 +++ new/zypp-boot-plugin-0.0.11/meson.build 2024-07-11 11:23:47.000000000 +0200 @@ -1,5 +1,5 @@ project('zypp-boot_plugin', 'cpp', - version : '0.0.10', + version : '0.0.11', license : 'LGPLv3', default_options : [ 'buildtype=debugoptimized', @@ -19,6 +19,7 @@ 'src/solvable-matcher.cc', 'src/zypp-commit-plugin.cc', 'src/zypp-plugin.cc', + 'src/stomp.cc', ) libeconf_dep = dependency('libeconf') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zypp-boot-plugin-0.0.10/src/stomp.cc new/zypp-boot-plugin-0.0.11/src/stomp.cc --- old/zypp-boot-plugin-0.0.10/src/stomp.cc 1970-01-01 01:00:00.000000000 +0100 +++ new/zypp-boot-plugin-0.0.11/src/stomp.cc 2024-07-11 11:23:47.000000000 +0200 @@ -0,0 +1,228 @@ +/* + * Copyright (c) [2019-2024] SUSE LLC + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact SUSE LLC. + * + * To contact SUSE about this file by physical or electronic mail, you may + * find current contact information at www.suse.com. + */ + + +#include <regex> + + +using namespace std; + + +#include "stomp.h" + + +namespace Stomp +{ + + Message + read_message(istream& is) + { + static const regex rx_command("[A-Za-z0-9_]+", regex::extended); + + enum class State { Start, Headers, Body } state = State::Start; + bool has_content_length = false; + ssize_t content_length = 0; + + Message msg; + + while (!is.eof()) + { + string line; + getline(is, line); + line = strip_cr(line); + + if (state == State::Start) + { + if (is.eof()) + return msg; // empty + + if (line.empty()) + continue; + + if (regex_match(line, rx_command)) + { + msg = Message(); + msg.command = line; + state = State::Headers; + } + else + { + throw runtime_error("stomp error: expected a command, got '" + line + "'"); + } + } + else if (state == State::Headers) + { + if (line.empty()) + { + state = State::Body; + + if (has_content_length) + { + if (content_length > 0) + { + vector<char> buf(content_length); + is.read(buf.data(), content_length); + msg.body.assign(buf.data(), content_length); + } + + // still read the \0 that terminates the frame + char buf2 = '-'; + is.read(&buf2, 1); + if (buf2 != '\0') + throw runtime_error("stomp error: missing \\0 at frame end"); + } + else + { + getline(is, msg.body, '\0'); + } + + return msg; + } + else + { + string::size_type pos = line.find(':'); + if (pos == string::npos) + throw runtime_error("stomp error: expected a header or new line, got '" + line + "'"); + + string key = unescape_header(line.substr(0, pos)); + string value = unescape_header(line.substr(pos + 1)); + + if (key == "content-length") + { + has_content_length = true; + content_length = std::stol(value.c_str()); + } + + msg.headers[key] = value; + } + } + } + + throw runtime_error("stomp error: expected a message, got a part of it"); + } + + + void + write_message(ostream& os, const Message& msg) + { + os << msg.command << '\n'; + for (auto it : msg.headers) + os << escape_header(it.first) << ':' << escape_header(it.second) << '\n'; + os << '\n'; + os << msg.body << '\0'; + os.flush(); + } + + + Message + ack() + { + Message msg; + msg.command = "ACK"; + return msg; + } + + + Message + nack() + { + Message msg; + msg.command = "NACK"; + return msg; + } + + + std::string + strip_cr(const std::string& in) + { + string::size_type length = in.size(); + + if (length > 0 && in[length - 1] == '\r') + return in.substr(0, length - 1); + + return in; + } + + + std::string + escape_header(const std::string& in) + { + string out; + + for (const char c : in) + { + switch (c) + { + case '\r': + out += "\\r"; break; + case '\n': + out += "\\n"; break; + case ':': + out += "\\c"; break; + case '\\': + out += "\\\\"; break; + + default: + out += c; + } + } + + return out; + } + + + std::string + unescape_header(const std::string& in) + { + string out; + + for (string::const_iterator it = in.begin(); it != in.end(); ++it) + { + if (*it == '\\') + { + if (++it == in.end()) + throw runtime_error("stomp error: invalid start of escape sequence"); + + switch (*it) + { + case 'r': + out += '\r'; break; + case 'n': + out += '\n'; break; + case 'c': + out += ':'; break; + case '\\': + out += '\\'; break; + + default: + throw runtime_error("stomp error: unknown escape sequence"); + } + } + else + { + out += *it; + } + } + + return out; + } + +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zypp-boot-plugin-0.0.10/src/stomp.h new/zypp-boot-plugin-0.0.11/src/stomp.h --- old/zypp-boot-plugin-0.0.10/src/stomp.h 1970-01-01 01:00:00.000000000 +0100 +++ new/zypp-boot-plugin-0.0.11/src/stomp.h 2024-07-11 11:23:47.000000000 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) [2019-2024] SUSE LLC + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact SUSE LLC. + * + * To contact SUSE about this file by physical or electronic mail, you may + * find current contact information at www.suse.com. + */ + + +#ifndef SNAPPER_STOMP_H +#define SNAPPER_STOMP_H + + +#include <istream> +#include <ostream> +#include <string> +#include <map> + + +/** + * A tiny STOMP (https://stomp.github.io/) implementation. + */ + +namespace Stomp +{ + + struct Message + { + std::string command; + std::map<std::string, std::string> headers; + std::string body; + }; + + + Message read_message(std::istream& is); + void write_message(std::ostream& os, const Message& msg); + + Message ack(); + Message nack(); + + std::string strip_cr(const std::string& in); + + std::string escape_header(const std::string& in); + std::string unescape_header(const std::string& in); + +} + + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zypp-boot-plugin-0.0.10/src/zypp-plugin.cc new/zypp-boot-plugin-0.0.11/src/zypp-plugin.cc --- old/zypp-boot-plugin-0.0.10/src/zypp-plugin.cc 2024-06-14 11:37:29.000000000 +0200 +++ new/zypp-boot-plugin-0.0.11/src/zypp-plugin.cc 2024-07-11 11:23:47.000000000 +0200 @@ -5,10 +5,8 @@ using namespace std; - #include "zypp-plugin.h" - int ZyppPlugin::main() { @@ -26,86 +24,6 @@ } -void -ZyppPlugin::write_message(ostream& os, const Message& msg) -{ - os << msg.command << endl; - for(auto it: msg.headers) { - os << it.first << ':' << it.second << endl; - } - os << endl; - os << msg.body << '\0'; - os.flush(); -} - - -ZyppPlugin::Message -ZyppPlugin::read_message(istream& is) -{ - enum class State { - Start, - Headers, - Body - } state = State::Start; - - Message msg; - - while (!is.eof()) - { - string line; - - getline(is, line); - boost::trim_right(line); - - if (state == State::Start) { - if (is.eof()) - return msg; //empty - - if (line.empty()) - continue; - - static const regex rx_word("[A-Za-z0-9_]+", regex::extended); - if (regex_match(line, rx_word)) - { - msg = Message(); - msg.command = line; - state = State::Headers; - } - else - { - throw runtime_error("Plugin protocol error: expected a command. Got '" + line + "'"); - } - } - else if (state == State::Headers) { - if (line.empty()) { - state = State::Body; - getline(is, msg.body, '\0'); - - return msg; - } - else - { - static const regex rx_header("([A-Za-z0-9_]+):[ \t]*(.+)", regex::extended); - smatch match; - - if (regex_match(line, match, rx_header)) - { - string key = match[1]; - string value = match[2]; - msg.headers[key] = value; - } - else - { - throw runtime_error("Plugin protocol error: expected a header or new line. Got '" + line + "'"); - } - } - } - } - - throw runtime_error("Plugin protocol error: expected a message, got a part of it"); -} - - ZyppPlugin::Message ZyppPlugin::dispatch(const Message& msg) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zypp-boot-plugin-0.0.10/src/zypp-plugin.h new/zypp-boot-plugin-0.0.11/src/zypp-plugin.h --- old/zypp-boot-plugin-0.0.10/src/zypp-plugin.h 2024-06-14 11:37:29.000000000 +0200 +++ new/zypp-boot-plugin-0.0.11/src/zypp-plugin.h 2024-07-11 11:23:47.000000000 +0200 @@ -2,18 +2,13 @@ #define ZYPP_PLUGIN_H #include <iostream> -#include <map> -#include <string> +#include "stomp.h" class ZyppPlugin { public: // Plugin message aka frame // https://doc.opensuse.org/projects/libzypp/HEAD/zypp-plugins.html - struct Message { - std::string command; - std::map<std::string, std::string> headers; - std::string body; - }; + using Message = Stomp::Message; /// Where the protocol reads from std::istream& pin; @@ -28,7 +23,8 @@ , pout(out) , plog(log) {} - virtual ~ZyppPlugin() {} + + virtual ~ZyppPlugin() = default; virtual int main(); @@ -38,15 +34,10 @@ // The base acks a _DISCONNECT and replies _ENOMETHOD to everything else. virtual Message dispatch(const Message&); - Message read_message(std::istream& is); - void write_message(std::ostream& os, const Message& msg); + Message read_message(std::istream& is) const { return Stomp::read_message(is); } + void write_message(std::ostream& os, const Message& msg) const { Stomp::write_message(os, msg); } - Message ack() { - Message a; - a.command = "ACK"; - std::cerr << "INFO:(boot-plugin):" << "RETURNING ACK" << std::endl; - return a; - } + Message ack() const { return Stomp::ack(); } }; #endif //ZYPP_PLUGIN_H