From 712b3c2b34e4371e687513d26aa825cb80b8449b Mon Sep 17 00:00:00 2001 From: redDwarf03 Date: Fri, 25 Apr 2025 20:58:53 +0200 Subject: [PATCH 1/3] Updates for macos sequoia to run retroshare-service --- src/CMakeLists.txt | 7 +- src/gxs/rsgxsnetservice.cc | 2 +- src/jsonapi/jsonapi-generator.py | 209 +++++++++++++++++++++++-------- src/libretroshare.pro | 2 +- src/retroshare/rsexpr.h | 5 +- src/use_libretroshare.pri | 10 +- 6 files changed, 173 insertions(+), 62 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 85ecf19ef9..a75aa555c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -234,7 +234,8 @@ list( pgp/pgpauxutils.cc pgp/pgphandler.cc pgp/pgpkeyutil.cc - pgp/rscertificate.cc ) + pgp/rscertificate.cc + pgp/rnppgphandler.cc ) list( APPEND RS_IMPLEMENTATION_HEADERS @@ -242,7 +243,8 @@ list( pgp/pgpauxutils.h pgp/pgphandler.h pgp/pgpkeyutil.h - pgp/rscertificate.h ) + pgp/rscertificate.h + pgp/rnppgphandler.h ) #./plugins/dlfcn_win32.cc #./plugins/dlfcn_win32.h @@ -329,6 +331,7 @@ list( pqi/pqisslpersongrp.h pqi/pqisslproxy.h pqi/pqissludp.h + pqi/pqissl.h pqi/pqistore.h pqi/pqistreamer.h pqi/pqithreadstreamer.h diff --git a/src/gxs/rsgxsnetservice.cc b/src/gxs/rsgxsnetservice.cc index 5ae4c51e62..6d5155a809 100644 --- a/src/gxs/rsgxsnetservice.cc +++ b/src/gxs/rsgxsnetservice.cc @@ -1656,7 +1656,7 @@ void RsGxsNetService::locked_checkDelay(uint32_t& time_in_secs) #include template -struct get_second : public std::unary_function +struct get_second { get_second(uint16_t serv_type,typename UpdateMap::key_type ItemClass::*member): mServType(serv_type),ID_member(member) {} diff --git a/src/jsonapi/jsonapi-generator.py b/src/jsonapi/jsonapi-generator.py index 1795469999..56990338c4 100755 --- a/src/jsonapi/jsonapi-generator.py +++ b/src/jsonapi/jsonapi-generator.py @@ -105,13 +105,13 @@ def processFile(file): defFileName = refid.rsplit('_',1)[0] + '.xml' print( 'Looking for', typeName, methodName, 'into', defFileName, - "calculated from refid:", refid ) + "calculated from refid:", refid ) try: defDoc = ET.parse(doxPrefix + defFileName).getroot() except FileNotFoundError: print( 'Can\'t open:', doxPrefix + defFileName, - "not found between:" ) + "not found between:" ) for mFileName in os.listdir(doxPrefix): print(mFileName) raise @@ -157,40 +157,92 @@ def processFile(file): callbackParams = '' for tmpPE in memberdef.findall('param'): - mp = MethodParam() - - pName = getText(tmpPE.find('declname')) - tmpDefval = tmpPE.find('defval') - mp._defval = getText(tmpDefval) if tmpDefval != None else '' pType = getText(tmpPE.find('type')) - - if pType.startswith('const '): pType = pType[6:] - if pType.startswith('std::function'): - if pType.endswith('&'): pType = pType[:-1] + is_likely_output_param = ('&' in pType and 'const' not in pType) + + # --- Robust Parameter Name Extraction (v3) --- + pName = '' + # 1. Try finding inside + paramNameNode = tmpPE.find('parametername') + if paramNameNode is not None and paramNameNode.text: + pName = paramNameNode.text + + # 2. Fallbacks (prioritize defname for likely output params) + if not pName: + declNameNode = tmpPE.find('declname') + defNameNode = tmpPE.find('defname') + + # Standard order: declname then defname + if not is_likely_output_param: + if declNameNode is not None and declNameNode.text: + pName = declNameNode.text + elif defNameNode is not None and defNameNode.text: + pName = defNameNode.text + # Reversed order for likely output params: defname then declname + else: + if defNameNode is not None and defNameNode.text: + pName = defNameNode.text + elif declNameNode is not None and declNameNode.text: + pName = declNameNode.text + # --- End of Name Extraction --- + + # Skip parameter if no name could be determined + if not pName: + print(f"Warning: Could not determine parameter name for param type [{pType}] in {refid}. Skipping.") + continue + + # Create and populate the MethodParam object + mp = MethodParam() + mp._name = pName # Assign the determined name FIRST + mp._type = pType # Assign the initial type + + tmpDefvalNode = tmpPE.find('defval') + mp._defval = getText(tmpDefvalNode) if tmpDefvalNode is not None else '' + mp._defval = ' '.join(mp._defval.split()) # Clean default value whitespace + + # --- Type Cleaning and Callback Detection --- + cleaned_pType = pType + if cleaned_pType.startswith('const '): + cleaned_pType = cleaned_pType[6:] + + if cleaned_pType.startswith('std::function'): + if cleaned_pType.endswith('&'): + cleaned_pType = cleaned_pType[:-1] + if pName.startswith('multiCallback'): mp._isMultiCallback = True hasMultiCallback = True + callbackName = pName + callbackParams = cleaned_pType elif pName.startswith('callback'): mp._isSingleCallback = True hasSingleCallback = True - callbackName = pName - callbackParams = pType - else: - pType = pType.replace('&', '').replace(' ', '') - - # Apparently some xml declarations include new lines ('\n') and/or multiple spaces - # Strip them using python magic - pType = ' '.join(pType.split()) - mp._defval = ' '.join(mp._defval.split()) - - mp._type = pType - mp._name = pName - + callbackName = pName + callbackParams = cleaned_pType + + mp._type = cleaned_pType # Assign cleaned signature for callbacks + + else: # Not a callback, just clean the regular type + # Don't remove '&' for regular types during cleaning here, + # it might be needed later for serialization/declaration. + # Just clean whitespace. + # cleaned_pType = cleaned_pType.replace('&', '').replace(' ', '') + cleaned_pType = ' '.join(cleaned_pType.split()) + mp._type = cleaned_pType # Assign cleaned type + # --- End of Type Cleaning --- + + # Add the parameter to the map and ordered list paramsMap[pName] = mp orderedParamNames.append(pName) for tmpPN in memberdef.findall('.//parametername'): - tmpParam = paramsMap[tmpPN.text] + # Add Try/Except block to handle cases where parameter name from docs doesn't match params from signature + try: + tmpParam = paramsMap[tmpPN.text] + except KeyError: + print(f"Warning: Parameter '{tmpPN.text}' found in Doxygen description for {refid}, but not in function signature parameters {list(paramsMap.keys())}. Skipping direction assignment.") + continue # Skip to the next parametername tag + tmpD = tmpPN.attrib['direction'] if 'direction' in tmpPN.attrib else '' if 'in' in tmpD: @@ -237,8 +289,27 @@ def processFile(file): paramsDeclaration = '' for pn in orderedParamNames: mp = paramsMap[pn] - paramsDeclaration += '\t\t' + mp._type + ' ' + mp._name - if mp._defval != '': + # Determine the type for declaration (remove reference qualifier) + declaration_type = mp._type + is_reference = False + if '&' in declaration_type: + is_reference = True + # Be careful not to remove '&' from pointer types like 'Type *&' if that occurs + # Assuming simple references 'Type&' or 'const Type&' for now + parts = declaration_type.split('&') + if len(parts) == 2 and parts[1].strip() == '': # Check it's likely a simple reference + declaration_type = parts[0].strip() + else: + # Handle more complex cases or leave as is if unsure + # For now, just log a warning if we encounter an unexpected reference type + print(f"Warning: Encountered potentially complex reference type '{mp._type}' for parameter '{mp._name}'. Declaration might be incorrect.") + declaration_type = declaration_type.replace('&', '').strip() # Fallback: simple removal + + paramsDeclaration += '\t\t' + declaration_type + ' ' + mp._name + # Handle default values - skip default assignment for references + # as it's problematic and likely the source of some errors. + # The function call will provide the value for output parameters. + if mp._defval != '' and not is_reference: paramsDeclaration += ' = ' + mp._defval paramsDeclaration += ';\n' if mp._in: @@ -281,35 +352,71 @@ def processFile(file): captureVars = 'this' callbackParamsSerialization = '' + callbackParameterListString = '' # Store just the parameter list e.g. "const Type& name" - if hasSingleCallback or hasMultiCallback or (callbackParams.find('(') + 2 < callbackParams.find(')')): + if hasSingleCallback or hasMultiCallback: + # Ensure callbackParams has the function signature before splitting + if not callbackParams: + print(f"ERROR: Callback parameter detected for {refid} but callbackParams string is empty!") + sys.exit(-1) + cbs = '' + + # Check if parentheses exist before splitting + if '(' not in callbackParams or ')' not in callbackParams: + print(f"ERROR: Could not parse callback parameters from signature '{callbackParams}' for {refid}") + sys.exit(-1) - callbackParams = callbackParams.split('(')[1] - callbackParams = callbackParams.split(')')[0] + try: + tmp_params = callbackParams.split('(', 1)[1] # Split only once + tmp_params = tmp_params.rsplit(')', 1)[0] # Split from right only once + callbackParameterListString = tmp_params # Store the extracted parameter list + except IndexError: + print(f"ERROR: IndexError while parsing callback parameters from signature '{callbackParams}' for {refid}") + sys.exit(-1) cbs += '\t\t\tRsGenericSerializer::SerializeContext ctx;\n' - for cbPar in callbackParams.split(','): - isConst = cbPar.startswith('const ') - pSep = ' ' - isRef = '&' in cbPar - if isRef: pSep = '&' - sepIndex = cbPar.rfind(pSep) + 1 - cpt = cbPar[0:sepIndex][6:] - cpn = cbPar[sepIndex:] - - cbs += '\t\t\tRsTypeSerializer::serial_process(' - cbs += 'RsGenericSerializer::TO_JSON, ctx, ' - if isConst: - cbs += 'const_cast<' - cbs += cpt - cbs += '>(' - cbs += cpn - if isConst: cbs += ')' - cbs += ', "' - cbs += cpn - cbs += '" );\n' + # Handle case with no parameters inside parentheses + if tmp_params.strip(): + for cbPar in tmp_params.split(','): + cbPar = cbPar.strip() # Clean whitespace + if not cbPar: continue # Skip if empty after split/strip + isConst = cbPar.startswith('const ') + pSep = ' ' + isRef = '&' in cbPar + if isRef: pSep = '&' + # Find the last occurrence of the separator to correctly split type and name + sepIndex = cbPar.rfind(pSep) + if sepIndex == -1: # Handle cases like single type without separator (e.g., 'void') + print(f"Warning: Could not properly parse callback parameter '{cbPar}' in {refid}. Assuming void/no name.") + continue + + sepIndex += 1 # Move index past the separator + cpt = cbPar[0:sepIndex].strip() # Type part + cpn = cbPar[sepIndex:].strip() # Name part + + # Ensure name part is a valid identifier (basic check) + if not cpn or not (cpn.isidentifier() or cpn.startswith('_')): + print(f"Warning: Parsed callback parameter name '{cpn}' from '{cbPar}' in {refid} seems invalid. Skipping serialization.") + continue + + # Adjust type part if it started with const + if isConst: cpt = cpt[6:].strip() + + cbs += '\t\t\tRsTypeSerializer::serial_process(' + cbs += 'RsGenericSerializer::TO_JSON, ctx, ' + if isConst: + cbs += 'const_cast<' + cbs += cpt + cbs += '>(' + cbs += cpn + if isConst: cbs += ')' + else: + cbs += cpn + cbs += ', \"' + cbs += cpn + cbs += '\" );\n' callbackParamsSerialization += cbs @@ -324,7 +431,7 @@ def processFile(file): substitutionsMap['sessionDelayedClose'] = sessionDelayedClose substitutionsMap['captureVars'] = captureVars substitutionsMap['callbackName'] = callbackName - substitutionsMap['callbackParams'] = callbackParams + substitutionsMap['callbackParams'] = callbackParameterListString substitutionsMap['callbackParamsSerialization'] = callbackParamsSerialization substitutionsMap['requiresAuth'] = 'true' if requiresAuth else 'false' diff --git a/src/libretroshare.pro b/src/libretroshare.pro index 3dfbfd241e..5eb407f830 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -1283,7 +1283,7 @@ rs_sam3_libsam3 { } libsam3.commands += \ cd $$shell_path($${LIBSAM3_BUILD_PATH}) && \ - $(MAKE) build $${LIBSAM3_MAKE_PARAMS} + $(MAKE) build CC=\"$$fixQmakeCC($$QMAKE_CC)\" $${LIBSAM3_MAKE_PARAMS} QMAKE_EXTRA_COMPILERS += libsam3 } diff --git a/src/retroshare/rsexpr.h b/src/retroshare/rsexpr.h index 562d6e3425..28878b80ef 100644 --- a/src/retroshare/rsexpr.h +++ b/src/retroshare/rsexpr.h @@ -24,10 +24,12 @@ #include #include #include +#include #include "util/rsprint.h" #include "retroshare/rstypes.h" #include "util/rstime.h" +#include "util/rsstring.h" /****************************************************************************************** Enumerations defining the Operators usable in the Boolean search expressions @@ -255,8 +257,7 @@ Binary Predicate for Case Insensitive search /*TODOS: *Factor locales in the comparison */ -struct CompareCharIC : - public std::binary_function< char , char , bool> { +struct CompareCharIC { bool operator () ( char ch1 , char ch2 ) const { return tolower( static_cast < unsigned char > (ch1) ) diff --git a/src/use_libretroshare.pri b/src/use_libretroshare.pri index 2183233e74..d09bbdf319 100644 --- a/src/use_libretroshare.pri +++ b/src/use_libretroshare.pri @@ -63,7 +63,8 @@ rs_rnplib { # Windows msys2 LIBRNP_LIBS *= -lbotan-3 } else { - LIBRNP_LIBS *= -lbotan-2 + # This is the case for macOS and other Unix-like systems + LIBRNP_LIBS *= -lbotan-3 } win32-g++|win32-clang-g++ { @@ -71,10 +72,9 @@ rs_rnplib { CONFIG += librnp_shared } - !libretroshare_shared { - # libretroshare is used as a static library. Link the external libraries to the executable. - LIBS *= $${LIBRNP_LIBS} - } + # Link LIBRNP_LIBS regardless of whether libretroshare is shared or static. + # This ensures the final executable can find the RNP symbols. + LIBS *= $${LIBRNP_LIBS} #PRE_TARGETDEPS += $$clean_path($${LIBRNP_BUILD_PATH}/src/lib/librnp.a) From 80b490d16661126cbee6d6d025166b763fa26838 Mon Sep 17 00:00:00 2001 From: Christoph Johannes Kleine Date: Sun, 3 Aug 2025 18:20:13 +0200 Subject: [PATCH 2/3] use botan2 --- src/use_libretroshare.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/use_libretroshare.pri b/src/use_libretroshare.pri index d09bbdf319..85377d0429 100644 --- a/src/use_libretroshare.pri +++ b/src/use_libretroshare.pri @@ -64,7 +64,7 @@ rs_rnplib { LIBRNP_LIBS *= -lbotan-3 } else { # This is the case for macOS and other Unix-like systems - LIBRNP_LIBS *= -lbotan-3 + LIBRNP_LIBS *= -lbotan-2 } win32-g++|win32-clang-g++ { From ca1d052f604ebb949df7f84705ef13956ad79009 Mon Sep 17 00:00:00 2001 From: Christoph Johannes Kleine Date: Mon, 4 Aug 2025 15:54:04 +0200 Subject: [PATCH 3/3] set mmacosx-version-min=10.13 --- src/libretroshare.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libretroshare.pro b/src/libretroshare.pro index 5eb407f830..c4f662b651 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -1189,6 +1189,8 @@ message("In rnp_rnplib precompilation code") # botan LIBRNP_CMAKE_PARAMS *= "-DBOTAN_INCLUDE_DIR=$$clean_path(/usr/local/opt/botan@2/include/botan-2)" LIBRNP_CMAKE_PARAMS *= "-DBOTAN_LIBRARY=$$clean_path(/usr/local/opt/botan@2/lib/libbotan-2.a)" + # set minimum Mac Version to not get different endresults of min versions + LIBRNP_CMAKE_CXXFLAGS = -mmacosx-version-min=10.13 } win32-g++ {