| @@ -371,43 +371,44 @@ | ||
| 371 | 371 | // Create new table row — MUST match the 8 columns in the |
| 372 | 372 | // <thead> exactly (id, business name, contact name, email, |
| 373 | 373 | // phone, username, role, actions). Skipping any of these |
| 374 | 374 | // makes every later cell shift one column to the left. |
| 375 | + var esc = function(v){ return $('<div>').text(v == null ? '' : String(v)).html(); }; | |
| 375 | 376 | var newRow = ` |
| 376 | 377 | <tr> |
| 377 | 378 | <td class="px-6 py-4 whitespace-nowrap"> |
| 378 | - <div class="text-sm text-gray-500 font-mono font-semibold">${response.data.client_id}</div> | |
| 379 | + <div class="text-sm text-gray-500 font-mono font-semibold">${esc(response.data.client_id)}</div> | |
| 379 | 380 | </td> |
| 380 | 381 | <td class="px-6 py-4 whitespace-nowrap"> |
| 381 | - <div class="text-sm font-medium text-gray-900">${businessName}</div> | |
| 382 | + <div class="text-sm font-medium text-gray-900">${esc(businessName)}</div> | |
| 382 | 383 | </td> |
| 383 | 384 | <td class="px-6 py-4 whitespace-nowrap"> |
| 384 | - <div class="text-sm font-medium text-gray-900">${contactName}</div> | |
| 385 | + <div class="text-sm font-medium text-gray-900">${esc(contactName)}</div> | |
| 385 | 386 | </td> |
| 386 | 387 | <td class="px-6 py-4 whitespace-nowrap"> |
| 387 | - <div class="text-sm text-gray-500">${clientData.email || ''}</div> | |
| 388 | + <div class="text-sm text-gray-500">${esc(clientData.email || '')}</div> | |
| 388 | 389 | </td> |
| 389 | 390 | <td class="px-6 py-4 whitespace-nowrap"> |
| 390 | - <div class="text-sm text-gray-500">${clientData.phone || ''}</div> | |
| 391 | + <div class="text-sm text-gray-500">${esc(clientData.phone || '')}</div> | |
| 391 | 392 | </td> |
| 392 | 393 | <td class="px-6 py-4 whitespace-nowrap"> |
| 393 | - <div class="text-sm text-gray-500">${clientData.username || ''}</div> | |
| 394 | + <div class="text-sm text-gray-500">${esc(clientData.username || '')}</div> | |
| 394 | 395 | </td> |
| 395 | 396 | <td class="px-6 py-4 whitespace-nowrap"> |
| 396 | 397 | <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"> |
| 397 | 398 | <i class="fas fa-user mr-1"></i> |
| 398 | - ${roleLabel} | |
| 399 | + ${esc(roleLabel)} | |
| 399 | 400 | </span> |
| 400 | 401 | </td> |
| 401 | 402 | <td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> |
| 402 | 403 | <div class="flex items-center space-x-2"> |
| 403 | - <a href="?page=easy-invoice-client-view&client_id=${response.data.client_id}" | |
| 404 | + <a href="?page=easy-invoice-client-view&client_id=${esc(response.data.client_id)}" | |
| 404 | 405 | class="inline-flex items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded text-indigo-700 bg-indigo-100 hover:bg-indigo-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors duration-200" |
| 405 | 406 | title="View Client"> |
| 406 | 407 | <i class="fas fa-eye mr-1"></i> |
| 407 | 408 | View |
| 408 | 409 | </a> |
| 409 | - <a href="?page=easy-invoice-client-edit&client_id=${response.data.client_id}" | |
| 410 | + <a href="?page=easy-invoice-client-edit&client_id=${esc(response.data.client_id)}" | |
| 410 | 411 | class="inline-flex items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded text-blue-700 bg-blue-100 hover:bg-blue-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200" |
| 411 | 412 | title="Edit Client"> |
| 412 | 413 | <i class="fas fa-edit mr-1"></i> |
| 413 | 414 | Edit |
| @@ -413,9 +414,9 @@ | ||
| 413 | 414 | Edit |
| 414 | 415 | </a> |
| 415 | 416 | <button type="button" |
| 416 | 417 | class="delete-client inline-flex items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded text-red-700 bg-red-100 hover:bg-red-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-colors duration-200" |
| 417 | - data-id="${response.data.client_id}" | |
| 418 | + data-id="${esc(response.data.client_id)}" | |
| 418 | 419 | title="Delete Client"> |
| 419 | 420 | <i class="fas fa-trash mr-1"></i> |
| 420 | 421 | Delete |
| 421 | 422 | </button> |