Join the Monal community chat
developYou can join the public Monal Multi-User Chat (MUC) via XMPP to interact with the community. Ensure you follow the project's Code of Conduct when participating.
xmpp:monal@chat.yax.imrepository·develop·Indexed 20 days ago
https://github.com/monal-im/monalA modern, cross-platform XMPP client for iOS and macOS supporting various XMPP Extension Protocols (XEPs). The project includes a suite of Rust-based utilities such as monal-html-parser for CSS-based HTML extraction, monal-xml-parser for incremental XML streaming, and sdp-to-jingle for converting between Session Description Protocol (SDP) and Jingle XML strings. It also provides a Python-based UDP log server for decrypting and decompressing AES-GCM encrypted JSON log packets.
You can join the public Monal Multi-User Chat (MUC) via XMPP to interact with the community. Ensure you follow the project's Code of Conduct when participating.
xmpp:monal@chat.yax.imMonal is available for iOS through the following channels:
info@monal-im.org. Once granted, download from the Monal alpha download site.You can install Monal on macOS using Homebrew. There are three available tracks: Stable, Beta, and Alpha.
@beta cask.# Install Stable version
brew install --cask monal
# Install Beta version
brew install --cask monal@beta
# Install Alpha version
brew tap monal-im/homebrew-monal-alpha
brew install --cask monal-alphainstall_panichandler(). This connects the Rust panic mechanism to a Swift-side handler that must be provided via the internal bridge.install_panichandler()The global_context() function returns an Arc<Context> that is shared globally across different parsers and threads. This context is used for namespace string sharing to optimize parsing performance. It is initialized lazily on the first call.
use monal_xml_parser::global_context;
let context = global_context();The MonalXmlStreamParser is designed for streaming XML data. You can feed it chunks of bytes and then poll it to receive parsed events. This is useful when XML data arrives in fragments (e.g., over a network socket).
MonalXmlStreamParser::new(capacity, max_token_length)..feed(chunk) method..poll() to retrieve the next parsed event. If the parser needs more data to complete an event, it returns MonalXmlStreamParserResult::NeedMoreData.use monal_xml_parser::{MonalXmlStreamParser, MonalXmlStreamParserResult};
let mut parser = MonalXmlStreamParser::new(1024, 4096);
// Feed a chunk of data
parser.feed(b"<message xmlns='http://xmpp.org'>Hello</message>");
// Poll for results
match parser.poll() {
Ok(MonalXmlStreamParserResult::Start(local, ns, attrs)) => {
println!("Start element: {} in namespace {}", local, ns);
}
Ok(MonalXmlStreamParserResult::Text(text)) => {
println!("Text content: {}", text);
}
Ok(MonalXmlStreamParserResult::End) => {
println!("End element");
}
Ok(MonalXmlStreamParserResult::NeedMoreData) => {
// Wait for more data via .feed()
}
Err(e) => println!("Parsing error: {}", e),
_ => {}
}The formatLogline(entry) function converts a decoded JSON log entry into a human-readable string.
Expected JSON structure for entry:
timestamp: String timestamp.flag: Integer representing the log level (e.g., 1 for ERROR, 4 for INFO).file: Path to the source file.line: Line number.message: The log message.function: The function name.threadID: The thread identifier.tag: A dictionary containing:processName: Name of the process.queueThreadLabel: Label for the queue thread.qosName: Quality of Service name.Output Format:
[timestamp] [LEVEL] [processName] [threadID:queueThreadLabel (QOS:qosName)] [parentDir/filename] [line]: [message]
def formatLogline(entry):
# ... implementation ...
return formatted_stringThe MonalHtmlParser allows you to parse HTML strings and select elements using CSS-like selectors.
new(html: String).select(selector: String, atrribute: Option<String>) to retrieve a list of strings representing the selected elements or their attributes.// Example usage in Swift
let parser = MonalHtmlParser(html: "<div><p class='text'>Hello</p></div>")
let classes = parser.select("p", atrribute: Some("class"))
// classes would contain ["text"]
let tags = parser.select("p", atrribute: nil)
// tags would contain ["<p class='text'>Hello</p>"]The MonalHtmlParser struct provides a wrapper around an HTML document, allowing you to extract text content or specific attribute values using CSS selectors.
To use it, initialize a new parser with a String containing the HTML content. You can then use the select method to find elements matching a CSS selector.
None as the atrribute argument, select returns a vector of the text content found within the matched elements.Some(attribute_name) as the atrribute argument, select returns a vector of the values of that specific attribute for each matched element.Note: If the provided CSS selector is invalid, the error is printed to stderr and an empty vector is returned.
use monal_html_parser::MonalHtmlParser;
let html = r#"<div class="item" id="test">Hello <span>World</span></div>"#.to_string();
let parser = MonalHtmlParser::new(html);
// Extract text content from elements matching the selector
let text_results = parser.select(".item".to_string(), None);
// Result: ["Hello World"]
// Extract a specific attribute value
let id_results = parser.select(".item".to_string(), Some("id".to_string()));
// Result: ["test"]The decrypt(ciphertext, key) function performs AES-GCM decryption.
Expected ciphertext format:
The key provided to this function should be the 32-byte (256-bit) derived key.
Raises:
Exception: If the IV length is not 12 bytes, the tag length is not 16 bytes, or if decryption/verification fails.def decrypt(ciphertext, key):
# ... implementation ...
return plaintextUse sdp_str_to_jingle_str to transform a Session Description Protocol (SDP) string into a Jingle-formatted XML string. This is useful for bridging WebRTC-style SDP descriptions with XMPP Jingle signaling.
Arguments:
sdp_str: The input SDP string to be parsed.initiator: A boolean indicating whether the caller is the session initiator. This affects how the Jingle session is constructed.Returns Some(String) containing the XML representation of the Jingle session if successful, or None if parsing or conversion fails.
let sdp = "v=0\r\no=- 4728394728394728394728394728394728394728\r\ns=-\r\n...";
if let Some(jingle_xml) = sdp_str_to_jingle_str(sdp, true) {
println!("Converted Jingle XML: {}", jingle_xml);
} else {
eprintln!("Failed to convert SDP to Jingle");
}