Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion frontend/lib/CPIM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export class CPIM {
static fromString(raw: string): CPIM {
let cpim = new CPIM();

let parts = raw.split("\n\n");
// CRLF normalization — Linphone-emitted CPIM uses CRLF per RFC 3862; mirrors PHP-side fix in src/CPIM.php
let parts = raw.replace(/\r\n/g, "\n").split("\n\n");
cpim.addHeaders(parts[0]);
cpim.addHeaders(parts[1]);

Expand Down
7 changes: 6 additions & 1 deletion lua/index.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ function uriescape (s)
return '%'..string.format("%02X", string.byte(c));
end
);
s = string.gsub(s, "%s", "+");
-- Encode whitespace as %20 (RFC 3986), not "+" (form-urlencoded). Together with the
-- first gsub above (which escapes literal "+" to %2B), this gives a fully RFC 3986–
-- consistent encoding. mod_curl decodes %XX in transit but leaves "+" literal, so the
-- receiving side (outbound-hook.php) must use rawurldecode (RFC 3986) to match.
-- Do NOT change to "+" without coordinating the decoder change in outbound-hook.php.
s = string.gsub(s, "%s", "%%20");
return s;
end

Expand Down
22 changes: 19 additions & 3 deletions outbound-hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,35 @@

// ── Normalize fields based on payload source ──
// Web UI sends extensionUUID (camelCase); FS event has extension_uuid (set by chatplan user_data)
//
// rawurldecode (RFC 3986) used on both branches:
//
// - FS-event branch: paired with lua/index.lua's `uriescape`, which encodes literal `+` as
// `%2B` (step 1) and whitespace as `%20` (step 2 — see Lua comment there). mod_curl
// decodes `%XX` in transit but leaves `+` literal. rawurldecode here is the matching
// decoder; effectively a no-op for properly-encoded bodies, defensive against residue.
// IMPORTANT: do NOT switch to urldecode without also reverting the Lua line-12 fix —
// the encoder and decoder must be consistent (RFC 3986 throughout). Mismatched
// urldecode form-urlencoded behavior would mangle literal `+` to space.
//
// - Web UI branch: frontend sends raw JSON (no `encodeURIComponent`/`encodeURI`), so
// $event->body and $event->id arrive as raw values from json_decode. rawurldecode is
// a no-op for these; chosen for consistency and to incidentally fix a latent
// `+`-corruption bug where urldecode would have mangled user-entered literal `+`.

if (isset($event->extensionUUID)) {
// Web UI payload (Ian's webtexting)
$to = $event->to;
$contentType = $event->contentType;
$body = urldecode($event->body);
$dedupeID = urldecode($event->id);
$body = rawurldecode($event->body);
$dedupeID = rawurldecode($event->id);
$extensionUUID = $event->extensionUUID;
} else {
// FreeSWITCH event payload (from chatplan Lua via mod_curl)
// extension_uuid set by chatplan: ${user_data(${from_user}@${from_host} var extension_uuid)}
$to = $event->to_user;
$contentType = isset($event->type) ? $event->type : 'text/plain';
$body = isset($event->_body) ? urldecode($event->_body) : '';
$body = isset($event->_body) ? rawurldecode($event->_body) : '';
$dedupeID = isset($event->{'sip_h_X-Message-ID'}) ? $event->{'sip_h_X-Message-ID'} : uuid();
$extensionUUID = $event->extension_uuid;
}
Expand Down
2 changes: 1 addition & 1 deletion threadlist.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ class='fas fa-check fa-fw'></span><span class='button-label never pad'>Start</sp

?>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.3/dist/umd/popper.min.js"></script>
<script src="js/webtexting.umd.js"></script>
<script src="js/webtexting.umd.js?v=<?php echo filemtime(__DIR__ . '/js/webtexting.umd.js'); ?>"></script>
<script type="text/javascript">
window.notification_data = <?php echo json_encode(array("extension_uuid" => $extension['extension_uuid'])); ?>;

Expand Down
Loading