Hi everyone,
We have a significant update to Tickets CAD available on GitHub and we're looking for testers. This is a great opportunity to support the project — we're all volunteers, and testing is one of the most valuable ways to contribute to this community. You don't need to be a developer to help. If you can install the software and click around, you're exactly who we need.
What's in this update:
How to get the update:
The latest version is available on GitHub at:
https://github.com/openises/tickets
SourceForge will not be updated immediately. GitHub is the place to get the latest version.
Option 1: Download as a ZIP file (easiest)
If you're not comfortable with git commands, you can download the entire project as a ZIP file:
tickets folder with the contentsOption 2: Using Git (recommended for ongoing updates, easiest to apply updates to)
If you have git installed (or want to try it), these commands will get you set up. Open a command prompt or terminal and run:
cd /path/to/your/webserver/htdocs
git clone https://github.com/openises/tickets.git
This creates a tickets folder with the latest code. If you've already cloned the repository previously, you can pull the latest changes instead:
cd /path/to/your/tickets
git pull origin main
That's it — two commands to stay current.
Back up first!
Before updating, please make a backup so you can easily revert if needed:
tickets folder to a safe location — for example, rename it to tickets_backup_20260314 or copy it somewhere outside your web server directory.mysqldump -u your_username -p your_database_name > tickets_backup_20260314.sql
incs/mysql.inc.php file contains your database connection settings. This file is not included in the repository, so it won't be overwritten — but it's good practice to back it up anyway.To revert to the previous version:
If you run into problems, simply:
tickets foldertickets folder to its original locationmysql -u your_username -p your_database_name < tickets_backup_20260314.sql
How to report issues:
If you find a bug or something doesn't work right, please reply to this message with:
If things are working well, we'd love to hear that too — a quick "tested on PHP 8.x, looks good" is genuinely helpful.
Thank you for your time and for being part of this community.
Eric Osterberg
--
You received this message because you are subscribed to the Google Groups "Open Source CAD - Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-source-cad-...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/open-source-cad---dev/f7c28cca-8022-4774-9866-eda40bd60fc1n%40googlegroups.com.
That's a security concern — unauthenticated users seeing navigation and potentially accessing pages like SOPs. Let me investigate immediately.
The index page uses frames — top.php (navbar) loads in the upper frame, and main.php loads in the lower frame. Both load immediately without any authentication check. Let me check top.php and main.php for auth gating:
Now let me see the navigation buttons section — what's rendered in the HTML:
Now I understand the full picture. Here's how top.php works:
<TR ID='buttons'>) is rendered with STYLE="display: none;" — it's hidden by defaultshow_butts() is only called inside the else block (logged in) at line 1113if (empty($_SESSION)) — pending login — skips show_butts(), mu_init(), etc.So the buttons are server-side rendered in the HTML but CSS-hidden and only shown via JavaScript show_butts() when logged in. However, the PHP-side is_guest() checks on lines 1383-1467 still emit the HTML for buttons like SOPs, Config, Reports, etc. — they're just hidden. The is_guest() function checks the session level, and when not logged in, the session is empty.
Let me check what is_guest() returns when there's no session:
When there's no session, is_guest() returns false (because array_key_exists('level', $_SESSION) is false). So !(is_guest()) evaluates to true when not logged in — meaning the SOPs button HTML and other restricted buttons ARE being rendered into the page for unauthenticated users!
The buttons are CSS-hidden (display:none), but:
go_there() function would navigate to pages in the main frameLet me check if target pages like config.php have their own auth checks:
Good findings. Now I have a clear picture:
The actual security issues:
top.php navbar rendering: When not logged in, is_guest() returns false, so !(is_guest()) is true — button HTML (including SOP path) is rendered server-side but CSS-hidden. The show_butts() JS function is only called when logged in, so buttons are invisible — but the HTML source leaks the SOP file path.
help.php has NO do_login() call — accessible without authentication.
emd_cards/demo.pdf is a static file directly accessible by URL without auth.
top.php itself has no do_login() — it relies on session checks in JavaScript, not PHP-side auth gating.
Let me now fix these issues:
Let me also check what do_login() does — it's the standard auth gating function:
Now let me check if top.php has a session_start():
top.php has session_start() at line 66 but NO do_login() — it handles login state purely through JavaScript in top_init(). The issue is that top.php is designed to work both pre-login and post-login (it's always the top frame), but it shouldn't render restricted button HTML when there's no authenticated session.
Now let me fix the issues. The best approach for top.php is to wrap the restricted button rendering in a PHP session check:
The proper fix: wrap the entire buttons row content in a session check so it's not even rendered into the HTML when not logged in. This way, no button HTML or SOP paths leak into the page source.
Now I need to close the PHP if block after all the buttons. Let me find where the buttons TD ends:
Now let me also protect the SOP card path from leaking. The $card_addr variable is set earlier and used in the button HTML. Let me check if it's also used elsewhere:
Good — $card_addr is only used in the SOP button which is now inside the auth-gated block. Now fix help.php:
Now protect the emd_cards directory. Let me check if .htaccess is being used elsewhere in this project:
Wait — deny from all would block the SOP card from loading for logged-in users too, since it's loaded via window.open() directly from the browser. The SOPs open as a PDF in a browser window via do_emd_card(). Let me check how that function works:
It opens the PDF directly via window.open(filename) — so a deny from all .htaccess would block it. Instead, I should create a PHP proxy script that checks authentication before serving the PDF. But that's a bigger change. For now, the most pragmatic approach is that since the nav button HTML with the SOP path is now auth-gated, unauthenticated users won't see the path. The emd_cards directory itself isn't advertised anywhere else. Let me check if there's directory listing enabled:
No directory index file and no root .htaccess. The SOP directory name emd_cards is predictable. Since we can't block direct access without breaking the SOP feature for logged-in users (it opens the PDF directly from the browser), the best protection is what we've already done — not leaking the file path in the HTML source to unauthenticated users.
Let me now lint the files and run tests:
Now let me also investigate the functions_major.inc.php line 1117 warning that the user reported. Let me look at that:
Line 1117: $theRow[0] — this is do_ticket_messages(). The $theRow parameter is being accessed with numeric index [0]. Let me find who calls do_ticket_messages():
Called from routes.php line 998 with $row_ticket. Let me check how $row_ticket is populated:
There it is! Line 694: $row_ticket = db_fetch_one(...) — which returns an associative array (via fetch_assoc()). But do_ticket_messages() accesses $theRow[0] at line 1117, expecting numeric index 0 to contain the ticket ID.
This is the same class of bug as the routes.php issue we fixed with db_fetch_one(). Our earlier fix made db_fetch_one() use fetch_array() (which returns both numeric and associative). Let me verify that fix is in place:
Our fix is already in place — fetch_array() returns both numeric and associative keys. So this warning should NOT be happening anymore with our fix. Unless the user saw this error before our fix was deployed, or there's a cached version.
Wait — let me re-read the user's message. They said "I have another error encountered with the dispatching menu, when I click on Show Messages, we see error message." This could be from a session before our db_fetch_one() fix. But let me also check the _nm version since the user might be on a non-internet session:
Same pattern at line 1935. Let me check if routes_nm.php also calls these functions:
OK, routes_nm.php uses fetch_array() directly (line 650), so it already has both numeric and associative keys. The issue is specifically with routes.php which uses db_fetch_one().
Since our fix to db_fetch_one() already changed it to use fetch_array(), the error on line 1117 should now be fixed. The user likely saw this error before our fix was applied. Let me verify by checking when the screenshot was taken vs our fix commit:
The user is showing us a screenshot from their current session. Our db_fetch_one() fix was in commit fbbe5da. The user may not have refreshed their browser since that fix. The fix IS already in place.
However, I notice there's still a fragile pattern — all these functions (do_ticket_extras, do_ticket_messages, do_ticket, do_ticket_only) rely on $theRow[0] to get the ticket ID. This is brittle. Let me make them more robust by using $theRow['id'] with a fallback:
Let me make these functions robust by preferring $theRow['id'] with fallback to $theRow[0]:
Let me re-read to get exact whitespace:
Tabs. Let me do smaller, targeted edits:
There's a duplicate in functions_major.inc.php. Let me find both occurrences:
There are three occurrences. Let me check each function that has $theRow[0]:
There are multiple functions with this pattern. Let me identify each function and fix them all. I see 4 functions:
do_ticket() (~line 1014)do_ticket_extras() (~line 1097, already partially fixed)do_ticket_messages() (~line 1118)Let me read each context:
Let me check what function contains lines ~1014 and ~1695:
Four functions with $theRow[0] pattern:
do_ticket() (line 949)do_ticket_extras() (already partially fixed with $theId)do_ticket_messages() (line 1112)do_ticket_wm() (line 1625)Let me fix each one. First, do_ticket() — need to add $theId extraction:
Now replace $theRow[0] with $theId in do_ticket():
Tab/space issues. Let me just replace each $theRow[0] individually using unique context:
Since these are inside do_ticket() which already has $theId defined, I need a different approach. Let me just do a global replace of $theRow[0] with $theId in this file since every function where it appears will have $theId defined:
Wait — but do_ticket_wm() and do_ticket_messages() don't have $theId yet. Let me add it to all of them first, then do the replacement. Let me use a different approach — just use sed:
Lines 952 and 1098 are the $theId definitions. I need to:
$theId to do_ticket_messages() (before line 1119)$theId to do_ticket_wm() (before line 1696)$theRow[0] usages (not the definition lines) with $theIdLet me first add $theId to do_ticket_messages():
Now add $theId to do_ticket_wm():
Wait, that's not right — array_merge will reset the $theRow and 0=>0 would just be overwritten. Let me undo that and do it properly:
Now replace the remaining $theRow[0] usages. Let me check current state:
Lines with $theId = are the definitions (keep as-is). The remaining usages at lines 1015, 1020, 1022, 1106, 1108, 1698, 1703, 1705, 1707 need to be changed. All of these have unique surrounding context due to different function call patterns. Let me do targeted edits:
Now do_ticket_extras() remaining uses:
Now do_ticket_wm():
Now verify no more $theRow[0] usages remain except the definitions:
All $theRow[0] usages are now only in the $theId definition lines (fallback). Now let me do the same for functions_major_nm.inc.php:
Same pattern in the _nm version. Let me find the function boundaries:
Now let me add $theId to each function in the _nm file and replace usages. Let me do these edits:
Now do_ticket_wm() in the _nm file:
Now do_ticket_extras() in _nm:
Tab issues again. Let me do these as smaller individual edits:
Now replace the remaining $theRow[0] in those two functions. Let me just use replace_all=true for the remaining usages since they're all the same pattern:
Lines 1920, 1925, 1927 are in do_ticket_extras, and 1938 is in do_ticket_messages. Let me fix them:
Now do_ticket_messages in _nm:
Now verify no more raw $theRow[0] usages in _nm:
All clean — only $theId definition lines remain. Now lint and test:
All tests pass. Now let me commit everything:
Here's a summary of what was found and fixed:
a3ee286The user report was valid. top.php renders navigation buttons server-side for all visitors — the buttons are CSS-hidden (display:none) and only shown via JavaScript show_butts() for authenticated users. However:
emd_cards/demo.pdf) to unauthenticated usersis_guest() check returns false when there's no session, so !(is_guest()) is true for unauthenticated users — meaning restricted buttons (SOPs, Config, Reports, Chat, etc.) were rendered into the HTMLFix: Wrapped the entire button rendering block in a $_SESSION['user_id'] check so no button HTML is emitted for unauthenticated visitors.
The only navigation target page with no do_login() call. All other pages (config, reports, units, search, etc.) properly gate via do_login().
Fix: Added session check that redirects to main.php if no authenticated session exists.
$theRow[0] Undefined Array Key Warning (Bug — Line 1117)The "Show Messages" error you saw (Undefined array key 0) was caused by do_ticket_messages() accessing $theRow[0] (numeric index) when the row was fetched via db_fetch_one() which returned only associative keys. Our earlier db_fetch_one() backward-compat fix added fetch_array(), but the code pattern was still fragile.
Fix: All 8 functions across both functions_major.inc.php and functions_major_nm.inc.php now use $theId = $theRow['id'] ?? $theRow[0] ?? 0 — preferring the named key with numeric fallback.
The emd_cards/demo.pdf is directly accessible by URL if someone knows the path. Since the SOP feature uses window.open() to display the PDF, we can't block it with .htaccess without breaking the feature. The path is no longer leaked in HTML source (fix #1), which is the primary mitigation.
To view this discussion visit https://groups.google.com/d/msgid/open-source-cad---dev/924496d4-867f-4ed1-bb2e-b175a451cb4fn%40googlegroups.com.
There are several discussions ongoing onlist and offline with direct emails.
Just to loop the list into my current project, I have spent a few hundred dollars on a Claude Code account and extra API credits so I can get the most out of my planned 36 hour coding sprint. My goal is to clean up the dead code, and fix security vulnerabilities. There are hundreds of issues that need revisions.
Here's the general outline. I'm not sure how far I'll get, but I set some pretty far reaching goals.
I'd call Phase 1 about 90% complete and phase 2 about 15% complete after about 40 hours of coding with Claude.
Testing is really important right now, as much as we can possibly test, I need your feedback.
Phase 1: Security fixes (SQL injection in 353 files, XSS, MD5 passwords, CSRF)
Phase 2: Code organization (eliminate duplicates, add Composer, separate concerns)
Phase 3: Database modernization (foreign keys, migrations, PDO)
Phase 4: UI modernization (replace framesets, responsive design, dark mode)
Phase 5: REST API layer (enable mobile and integrations)
Phase 6: Mobile application (React Native or Flutter)
Phase 7: Full rewrite consideration (Python/FastAPI + React recommended)
Includes architecture diagrams and feature gap analysis vs. commercial CAD systems
---
All three fixes from the contributor are in — commit d266d88. Here's what was done:
The problem: The index.php version check ($installedVersion !== $version) was redirecting to install.php any time the database version didn't match the code version. But since install.php loads in the main frame (not the top-level frameset), the user got a blank page with no login form.
The fix (3 parts, as specified by the contributor):
index.php — Changed from $installedVersion === null || $installedVersion !== $version to just $installedVersion === null. This only redirects fresh installs (no version at all), not upgrades.
login.inc.php redir() — Added $top = FALSE parameter. When $top = TRUE, uses top.location.href via JavaScript to break out of the frameset, with a <noscript> fallback to the original meta refresh.
login.inc.php post-login — After successful authentication, admin+ users get a version mismatch check. If the database version differs from the installer version, they're redirected to install.php using the new top-frame redirect, so the installer loads in the full browser window.
The contributor's observation about the dual abstraction layers (mysql2i shim + db.inc.php) is valid and I've documented it in KNOWN_ISSUES.md with the recommendation to consolidate on db.inc.php as the single layer going forward. That's already the direction Phase 3 is heading.
His point about AI-generated "spaghetti code with parallel redundancies" is well-taken — that's exactly why we're doing thorough testing and the KNOWN_ISSUES.md tracker exists.
To view this discussion visit https://groups.google.com/d/msgid/open-source-cad---dev/b946fe27-6181-4741-9237-d01db9ec9d56n%40googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/open-source-cad---dev/92560efe-486d-4677-8cc9-d9605ecea4f7n%40googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/open-source-cad---dev/4c26f81a-1bdd-4742-9228-fe6b9d88dc7cn%40googlegroups.com.
You received this message because you are subscribed to a topic in the Google Groups "Open Source CAD - Dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/open-source-cad---dev/k6A77B0t3cc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to open-source-cad-...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/open-source-cad---dev/CAJLaYFV328Du0mPLXmr_Q%2B99b-gCskXjwbthnQi1tCjPLMo7RQ%40mail.gmail.com.