Sync differences from branch 'master' into 'devel' after release 1.13.3

This commit is contained in:
Matej Kenda 2024-04-05 11:47:42 +02:00
parent 534c12415e
commit bd4560123f
23 changed files with 140 additions and 29 deletions

View File

@ -1,6 +1,37 @@
This is the changelog file for the POCO C++ Libraries. This is the changelog file for the POCO C++ Libraries.
Release 1.13.3 (2024-04-04)
===========================
Summary of Changes:
This is a bugfix release.
Security Fixes:
- GH #4496 Upgrade bundled libexpat to 2.6.2
Features, Enhancements and Third Party Updates:
- GH #4488 Add Poco::Util::Timer::idle() method to check if timer has any tasks scheduled
- GH #3807 DNS.resolve() should not be sorted in HostEntry::removeDuplicates()
- GH #4515 Upgrade bundled SQLite to 3.45.2
- PR #4517 Optimize Net module for Android
Bug Fixes and Improvements:
- GH #4505 ODBC Unicode wrappers do not check for null length pointers
- GH #4492 Poco::BasicMemoryStreamBuf is missing seekpos()
- GH #4486 DateTimeFormat RFC1036 Sunday name is short (should be long)
- GH #4468 Poco::URI: don't lowercase host part if it's a Unix domain socket
- GH #4450 Error between Poco::ActiveRecord and Poco::Data::PostgreSQL
- GH #4435 SecureStreamSocket is not thread-safe
- GH #4415 SecureSocketImpl::reset shouldn't close socket
- GH #3857 Thread_POSIX.cpp shouldn't convert thread IDs to long
- GH #3725 secure socket receiveTimeout throwing after configured timeout * 2
Release 1.13.2 (2024-02-19) Release 1.13.2 (2024-02-19)
=========================== ===========================
@ -38,7 +69,7 @@ Features and Enhancements:
Bug Fixes and Improvements: Bug Fixes and Improvements:
- GH #4443 Upgrade libexpat to 2.6.0 - GH #4443 Upgrade libexpat to 2.6.0
- GH #4425 Unit tests: optional testing of deprecated functionality - GH #4425 Unit tests: optional testing of deprecated functionality
- GH #4421 Multiple calls to initializeSSL/uninitializeSSL cause assert failure during certificate validation - GH #4421 Multiple calls to initializeSSL/uninitializeSSL cause assert failure during certificate validation
- GH #4411 NULL pointer: strategy when setting rotation never in FileChannel - GH #4411 NULL pointer: strategy when setting rotation never in FileChannel

View File

@ -65,3 +65,4 @@ Andrew Auclair
Jochen Sprickerhof Jochen Sprickerhof
Jesse Hoogervorst Jesse Hoogervorst
Aron Budea Aron Budea
zhuzeitou

View File

@ -11,5 +11,6 @@ vc.project.compiler.include = ..\\Foundation\\include
vc.project.compiler.defines.shared = ${vc.project.name}_EXPORTS vc.project.compiler.defines.shared = ${vc.project.name}_EXPORTS
vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.solution.create = true vc.solution.create = true
vc.solution.include = testsuite\\TestSuite vc.solution.include = testsuite\\TestSuite

View File

@ -60,6 +60,7 @@ public:
OP_GE, // >= OP_GE, // >=
OP_SHR, // >> OP_SHR, // >>
OP_SHR_ASSIGN, // >>= OP_SHR_ASSIGN, // >>=
OP_SPACESHIP, // <=>
OP_ASSIGN, // = OP_ASSIGN, // =
OP_EQ, // == OP_EQ, // ==
OP_NOT, // ! OP_NOT, // !

View File

@ -125,6 +125,14 @@ public:
const std::string& getLibrary() const; const std::string& getLibrary() const;
/// Returns the symbol's library. /// Returns the symbol's library.
void setOrder(std::size_t order);
/// Sets the order of the symbol within its container.
///
/// Currently only used for struct/class members.
std::size_t getOrder() const;
/// Returns the order of the symbol within its container.
const Attributes& attrs() const; const Attributes& attrs() const;
/// Returns the symbol's attributes. /// Returns the symbol's attributes.
@ -175,6 +183,7 @@ private:
int _line; int _line;
std::string _package; std::string _package;
std::string _library; std::string _library;
std::size_t _order;
Attributes _attrs; Attributes _attrs;
std::string _attributeList; std::string _attributeList;
@ -245,6 +254,12 @@ inline const std::string& Symbol::getLibrary() const
} }
inline std::size_t Symbol::getOrder() const
{
return _order;
}
inline const Attributes& Symbol::attrs() const inline const Attributes& Symbol::attrs() const
{ {
return _attrs; return _attrs;

View File

@ -66,6 +66,7 @@ OperatorToken::OperatorToken()
_opMap[">="] = i++; _opMap[">="] = i++;
_opMap[">>"] = i++; _opMap[">>"] = i++;
_opMap[">>="] = i++; _opMap[">>="] = i++;
_opMap["<=>"] = i++;
_opMap["="] = i++; _opMap["="] = i++;
_opMap["=="] = i++; _opMap["=="] = i++;
_opMap["!"] = i++; _opMap["!"] = i++;
@ -194,8 +195,14 @@ void OperatorToken::finish(std::istream& istr)
{ {
_value += (char) istr.get(); _value += (char) istr.get();
next = (char) istr.peek(); next = (char) istr.peek();
if (next == '=') _value += (char) istr.get();
}
else if (next == '=')
{
_value += (char) istr.get();
next = (char) istr.peek();
if (next == '>') _value += (char) istr.get();
} }
if (next == '=') _value += (char) istr.get();
break; break;
case '>': case '>':
if (next == '>') if (next == '>')

View File

@ -49,7 +49,8 @@ NameSpace::~NameSpace()
void NameSpace::addSymbol(Symbol* pSymbol) void NameSpace::addSymbol(Symbol* pSymbol)
{ {
poco_check_ptr (pSymbol); poco_check_ptr (pSymbol);
pSymbol->setOrder(_symbols.size());
_symbols.insert(SymbolTable::value_type(pSymbol->name(), pSymbol)); _symbols.insert(SymbolTable::value_type(pSymbol->name(), pSymbol));
} }
@ -65,7 +66,7 @@ void NameSpace::importSymbol(const std::string& fullName)
} }
} }
void NameSpace::importNameSpace(const std::string& nameSpace) void NameSpace::importNameSpace(const std::string& nameSpace)
{ {
_importedNameSpaces.push_back(nameSpace); _importedNameSpaces.push_back(nameSpace);
@ -94,7 +95,7 @@ Symbol* NameSpace::lookup(const std::string& name) const
Symbol* NameSpace::lookup(const std::string& name, std::set<const NameSpace*>& alreadyVisited) const Symbol* NameSpace::lookup(const std::string& name, std::set<const NameSpace*>& alreadyVisited) const
{ {
Symbol* pSymbol = 0; Symbol* pSymbol = 0;
if (name.empty()) if (name.empty())
return pSymbol; return pSymbol;
@ -104,11 +105,11 @@ Symbol* NameSpace::lookup(const std::string& name, std::set<const NameSpace*>& a
std::string head; std::string head;
std::string tail; std::string tail;
splitName(name, head, tail); splitName(name, head, tail);
alreadyVisited.insert(this); alreadyVisited.insert(this);
bool currentNSInserted = true; bool currentNSInserted = true;
if (head.empty()) if (head.empty())
{ {
alreadyVisited.insert(this); alreadyVisited.insert(this);
return root()->lookup(tail, alreadyVisited); return root()->lookup(tail, alreadyVisited);
@ -161,13 +162,13 @@ void NameSpace::nameSpaces(SymbolTable& table) const
extract(Symbol::SYM_NAMESPACE, table); extract(Symbol::SYM_NAMESPACE, table);
} }
void NameSpace::typeDefs(SymbolTable& table) const void NameSpace::typeDefs(SymbolTable& table) const
{ {
extract(Symbol::SYM_TYPEDEF, table); extract(Symbol::SYM_TYPEDEF, table);
} }
void NameSpace::typeAliases(SymbolTable& table) const void NameSpace::typeAliases(SymbolTable& table) const
{ {
extract(Symbol::SYM_TYPEALIAS, table); extract(Symbol::SYM_TYPEALIAS, table);
@ -179,19 +180,19 @@ void NameSpace::enums(SymbolTable& table) const
extract(Symbol::SYM_ENUM, table); extract(Symbol::SYM_ENUM, table);
} }
void NameSpace::classes(SymbolTable& table) const void NameSpace::classes(SymbolTable& table) const
{ {
extract(Symbol::SYM_STRUCT, table); extract(Symbol::SYM_STRUCT, table);
} }
void NameSpace::functions(SymbolTable& table) const void NameSpace::functions(SymbolTable& table) const
{ {
extract(Symbol::SYM_FUNCTION, table); extract(Symbol::SYM_FUNCTION, table);
} }
void NameSpace::variables(SymbolTable& table) const void NameSpace::variables(SymbolTable& table) const
{ {
extract(Symbol::SYM_VARIABLE, table); extract(Symbol::SYM_VARIABLE, table);
@ -226,7 +227,7 @@ void NameSpace::splitName(const std::string& name, std::string& head, std::strin
head.assign(name, 0, pos); head.assign(name, 0, pos);
pos += 2; pos += 2;
poco_assert (pos < name.length()); poco_assert (pos < name.length());
tail.assign(name, pos, name.length() - pos); tail.assign(name, pos, name.length() - pos);
} }
else head = name; else head = name;
} }

View File

@ -31,7 +31,8 @@ Symbol::Symbol():
_id(_nextId++), _id(_nextId++),
_pNameSpace(0), _pNameSpace(0),
_access(ACC_PUBLIC), _access(ACC_PUBLIC),
_line(-1) _line(-1),
_order(0)
{ {
} }
@ -41,7 +42,8 @@ Symbol::Symbol(const std::string& name, NameSpace* pNameSpace):
_name(name), _name(name),
_pNameSpace(pNameSpace), _pNameSpace(pNameSpace),
_access(ACC_PUBLIC), _access(ACC_PUBLIC),
_line(-1) _line(-1),
_order(0)
{ {
if (_pNameSpace) if (_pNameSpace)
_pNameSpace->addSymbol(this); _pNameSpace->addSymbol(this);
@ -103,6 +105,12 @@ void Symbol::setLibrary(const std::string& library)
} }
void Symbol::setOrder(std::size_t order)
{
_order = order;
}
std::string Symbol::fullName() const std::string Symbol::fullName() const
{ {
std::string fullName; std::string fullName;

View File

@ -7,4 +7,5 @@ vc.project.platforms = Win32
vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md
vc.project.prototype = TestSuite_vs90.vcproj vc.project.prototype = TestSuite_vs90.vcproj
vc.project.compiler.include = ..\\..\\Foundation\\include vc.project.compiler.include = ..\\..\\Foundation\\include
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.project.linker.dependencies = iphlpapi.lib vc.project.linker.dependencies = iphlpapi.lib

View File

@ -77,7 +77,7 @@ void CppParserTest::testExtractName()
decl = "void func(int arg1, int arg2)"; decl = "void func(int arg1, int arg2)";
name = Symbol::extractName(decl); name = Symbol::extractName(decl);
assertTrue (name == "func"); assertTrue (name == "func");
decl = "std::function<bool> func"; decl = "std::function<bool> func";
name = Symbol::extractName(decl); name = Symbol::extractName(decl);
assertTrue (name == "func"); assertTrue (name == "func");

View File

@ -12,5 +12,6 @@ vc.project.compiler.defines = POCO_NO_AUTOMATIC_LIBS
vc.project.compiler.defines.shared = ${vc.project.name}_EXPORTS vc.project.compiler.defines.shared = ${vc.project.name}_EXPORTS
vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.solution.create = true vc.solution.create = true
vc.solution.include = vc.solution.include =

View File

@ -4,8 +4,8 @@
#include "winres.h" #include "winres.h"
#define POCO_VERSION 1,13,1,0 #define POCO_VERSION 1,13,3,0
#define POCO_VERSION_STR "1.13.1" #define POCO_VERSION_STR "1.13.3"
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION POCO_VERSION FILEVERSION POCO_VERSION
@ -28,7 +28,6 @@ BEGIN
VALUE "FileDescription", "This file is part of the POCO C++ Libraries." VALUE "FileDescription", "This file is part of the POCO C++ Libraries."
VALUE "FileVersion", POCO_VERSION_STR VALUE "FileVersion", POCO_VERSION_STR
VALUE "InternalName", "POCO" VALUE "InternalName", "POCO"
VALUE "LegalCopyright", "Copyright (C) 2004-2024, Applied Informatics Software Engineering GmbH and Contributors."
VALUE "ProductName", "POCO C++ Libraries - https://pocoproject.org" VALUE "ProductName", "POCO C++ Libraries - https://pocoproject.org"
VALUE "ProductVersion", POCO_VERSION_STR VALUE "ProductVersion", POCO_VERSION_STR
END END

View File

@ -12,5 +12,6 @@ vc.project.compiler.defines =
vc.project.compiler.defines.shared = vc.project.compiler.defines.shared =
vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.project.linker.dependencies = ws2_32.lib iphlpapi.lib vc.project.linker.dependencies = ws2_32.lib iphlpapi.lib
vc.solution.create = true vc.solution.create = true

View File

@ -12,5 +12,6 @@ vc.project.compiler.defines =
vc.project.compiler.defines.shared = ${vc.project.name}_EXPORTS vc.project.compiler.defines.shared = ${vc.project.name}_EXPORTS
vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.debug_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared} vc.project.compiler.defines.release_shared = ${vc.project.compiler.defines.shared}
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.solution.create = true vc.solution.create = true
vc.solution.include = testsuite\\TestSuite vc.solution.include = testsuite\\TestSuite

View File

@ -7,4 +7,5 @@ vc.project.platforms = Win32
vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md
vc.project.prototype = ${vc.project.name}_vs90.vcproj vc.project.prototype = ${vc.project.name}_vs90.vcproj
vc.project.compiler.include = ..\\..\\..\\Foundation\\include;..\\..\\..\\Encodings\\include vc.project.compiler.include = ..\\..\\..\\Foundation\\include;..\\..\\..\\Encodings\\include
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.project.linker.dependencies.Win32 = ws2_32.lib iphlpapi.lib vc.project.linker.dependencies.Win32 = ws2_32.lib iphlpapi.lib

View File

@ -7,3 +7,4 @@ vc.project.platforms = Win32
vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md
vc.project.prototype = TestSuite_vs90.vcproj vc.project.prototype = TestSuite_vs90.vcproj
vc.project.compiler.include = ..\\..\\Foundation\\include;..\\..\\Encodings\\include vc.project.compiler.include = ..\\..\\Foundation\\include;..\\..\\Encodings\\include
vc.project.compiler.additionalOptions = /Zc:__cplusplus

View File

@ -36,6 +36,6 @@
// Bx: beta releases // Bx: beta releases
// //
#define POCO_VERSION 0x010D0100 #define POCO_VERSION 0x010D0300
#endif // Foundation_Version_INCLUDED #endif // Foundation_Version_INCLUDED

View File

@ -7,4 +7,5 @@ vc.project.platforms = Win32
vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md
vc.project.prototype = ${vc.project.name}_vs90.vcproj vc.project.prototype = ${vc.project.name}_vs90.vcproj
vc.project.compiler.include = ..\\..\\..\\Foundation\\include vc.project.compiler.include = ..\\..\\..\\Foundation\\include
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.project.linker.dependencies.Win32 = ws2_32.lib iphlpapi.lib vc.project.linker.dependencies.Win32 = ws2_32.lib iphlpapi.lib

View File

@ -7,4 +7,5 @@ vc.project.platforms = Win32
vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md vc.project.configurations = debug_shared, release_shared, debug_static_mt, release_static_mt, debug_static_md, release_static_md
vc.project.prototype = ${vc.project.name}_vs90.vcproj vc.project.prototype = ${vc.project.name}_vs90.vcproj
vc.project.compiler.include = ..\\..\\..\\Foundation\\include vc.project.compiler.include = ..\\..\\..\\Foundation\\include
vc.project.compiler.additionalOptions = /Zc:__cplusplus
vc.project.linker.dependencies.Win32 = ws2_32.lib iphlpapi.lib vc.project.linker.dependencies.Win32 = ws2_32.lib iphlpapi.lib

View File

@ -1 +1 @@
1.13.1 1.13.3

View File

@ -1,6 +1,35 @@
POCO C++ Libraries Release Notes POCO C++ Libraries Release Notes
AAAIntroduction AAAIntroduction
!!!Release 1.13.3
!!Summary of Changes
This is a bugfix release.
!!Security Fixes
- GH #4496 Upgrade bundled libexpat to 2.6.2
!!Features, Enhancements and Third Party Updates
- GH #4488 Add Poco::Util::Timer::idle() method to check if timer has any tasks scheduled
- GH #3807 DNS.resolve() should not be sorted in HostEntry::removeDuplicates()
- GH #4515 Upgrade bundled SQLite to 3.45.2
- PR #4517 Optimize Net module for Android
!!Bug Fixes and Improvements:
- GH #4505 ODBC Unicode wrappers do not check for null length pointers
- GH #4492 Poco::BasicMemoryStreamBuf is missing seekpos()
- GH #4486 DateTimeFormat RFC1036 Sunday name is short (should be long)
- GH #4468 Poco::URI: don't lowercase host part if it's a Unix domain socket
- GH #4450 Error between Poco::ActiveRecord and Poco::Data::PostgreSQL
- GH #4435 SecureStreamSocket is not thread-safe
- GH #4415 SecureSocketImpl::reset shouldn't close socket
- GH #3857 Thread_POSIX.cpp shouldn't convert thread IDs to long
- GH #3725 secure socket receiveTimeout throwing after configured timeout * 2
!!!Release 1.13.2 !!!Release 1.13.2

View File

@ -32,20 +32,30 @@ echo
gh issue list -S 'milestone:"'"${MILESTONE}"'" label:breaking' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"' gh issue list -S 'milestone:"'"${MILESTONE}"'" label:breaking' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"'
gh pr list -S 'milestone:"'"${MILESTONE}"'" label:breaking' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"' gh pr list -S 'milestone:"'"${MILESTONE}"'" label:breaking' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"'
echo echo
echo "Features and Enhancements:" echo "Security Fixes:"
echo echo
gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking label:enhancement' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"' gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking label:security' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"'
gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:enhancement label:feature' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"' gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking label:security' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"'
gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking label:enhancement' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"'
gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:enhancement label:feature' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"' echo
echo "Features, Enhancements and Third Party Updates:"
echo
gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:security label:enhancement' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"'
gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:security -label:enhancement label:feature' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"'
gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:security -label:enhancement -label:feature label:third-party' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"'
gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:security label:enhancement' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"'
gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:security -label:enhancement label:feature' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"'
gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:security -label:enhancement -label:feature label:third-party' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"'
echo echo
echo "Bug Fixes and Improvements:" echo "Bug Fixes and Improvements:"
echo echo
gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:enhancement -label:feature' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"' gh issue list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:enhancement -label:feature -label:security -label:third-party' -s all -L 500 --json number,title --jq '.[] | "- GH #\(.number) \(.title)"'
gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:enhancement -label:feature' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"' gh pr list -S 'milestone:"'"${MILESTONE}"'" -label:breaking -label:enhancement -label:feature -label:security -label:third-party' -s all -L 500 --json number,title --jq '.[] | "- PR #\(.number) \(.title)"'
echo echo

View File

@ -1 +1 @@
101 103