1var loaded = false; 2 3var search_current_page = 1; 4var search_current_news = 1; 5var search_current_multimedia = 1; 6var search_current_document = 1; 7var search_local_storage_prefix = 'RENWEBSITE_'; 8var search_local_storage_max = 16; 9var search_local_storage_cols = 4; 10var search_local_storage_col_max = 4; 11 12var divElementTag = "<div>"; 13var ulElementTag = "<ul>"; 14var liElementTag = "<li>"; 15var aElementTag = "<a>"; 16 17window.onload = function () { 18 if (document.readyState == 'complete' && !loaded) { 19 readUrlParameterSearch(); 20 setPageRecentSearches(); 21 handleInputs(); 22 23 loaded = true; 24 } 25}; 26 27handleInputs(); 28 29function handleInputs() { 30 var input_search_global = document.getElementById("ws_txt_search_global"); 31 if (input_search_global != null) { 32 input_search_global.addEventListener("keypress", function (event) { 33 if (event.key === "Enter") { 34 event.preventDefault(); 35 var headerSearchForm = document.getElementById('header-search-form'); 36 if (headerSearchForm != null) { 37 let searchUrl = headerSearchForm.dataset.spUrl; 38 goToSearchPage(searchUrl); 39 } 40 } 41 }); 42 } 43 44 var input_search_global_principal = document.getElementById("ws_txt_search_global_principal"); 45 if (input_search_global_principal != null) { 46 input_search_global_principal.addEventListener("keypress", function (event) { 47 if (event.key === "Enter") { 48 event.preventDefault(); 49 searchMain(); 50 } 51 }); 52 } 53} 54 55function readUrlParameterSearch() { 56 let searchParams = (new URL(document.location)).searchParams; 57 58 let sParam = searchParams.get("s"); 59 if (sParam != null) { 60 document.getElementById('ws_txt_search_global_principal').value = decodeURI(unescapeHtml(sParam)); 61 } 62 63 let cParam = searchParams.get("c"); 64 if (cParam != null) { 65 var categories = unescapeHtml(cParam).split(';') 66 for (var i = 0; i < categories.length; i++) { 67 if (categories.at(i) !== '') { 68 var _tag = document.getElementById("searchMainCat_" + categories.at(i)); 69 if (_tag != null) { 70 _tag.classList.remove('tag-ren'); 71 _tag.classList.add('tag-ren_special'); 72 } 73 } 74 } 75 } 76 77 let ppParam = searchParams.get("pp"); 78 if (ppParam != null) { 79 search_current_page = parseInt(unescapeHtml(ppParam)); 80 } 81 82 let piParam = searchParams.get("pi"); 83 if (piParam != null) { 84 search_current_news = parseInt(unescapeHtml(piParam)); 85 } 86 87 let pvParam = searchParams.get("pv"); 88 if (pvParam != null) { 89 search_current_multimedia = parseInt(unescapeHtml(pvParam)); 90 } 91 92 let pdParam = searchParams.get("pd"); 93 if (pdParam != null) { 94 search_current_document = parseInt(unescapeHtml(pdParam)); 95 } 96 97 let pTab = searchParams.get("t"); 98 if (pTab != null) { 99 let tabId = '.btn-ren--tabs-slim#'; 100 let tabIndex = parseInt(unescapeHtml(pTab)); 101 102 switch (tabIndex) { 103 case 1: 104 tabId += 'tab-pages'; 105 break; 106 case 2: 107 tabId += 'tab-news'; 108 break; 109 case 3: 110 tabId += 'tab-multimedia'; 111 break; 112 case 4: 113 tabId += 'tab-documents'; 114 break; 115 default: 116 tabId += 'tab-pages'; 117 break; 118 } 119 120 $(tabId).click(); 121 } 122} 123 124function pageSearchByCat(category) { 125 search_current_page = 1; 126 127 let _category = document.getElementById("searchMainCat_" + category); 128 if (_category.classList.contains('tag-ren_special')) { 129 _category.classList.remove('tag-ren_special'); 130 _category.classList.add('tag-ren'); 131 } 132 else { 133 _category.classList.add('tag-ren_special'); 134 } 135 136 let categories = []; 137 let selectedCategories = document.getElementsByClassName("tag-ren_special"); 138 for (var i = 0; i < selectedCategories.length; i++) { 139 categories.push(selectedCategories.item(i).id.replace('searchMainCat_', '')); 140 } 141 142 let searchCategoriesUrl = getSeachBase() + '&c=' + encodeURI(categories.join(';')); 143 setBrowserLocation(searchCategoriesUrl); 144} 145 146function pageSearchByText() { 147 setBrowserLocation(getSeachBase()); 148} 149 150function getSeachBase() { 151 let element = document.getElementById('ws_txt_search_global_principal'); 152 let textToSearch = ""; 153 154 if (element) { 155 textToSearch = escapeSearchTextToHTML(element.value); 156 } 157 158 return encodeURI(__searchPageUrl) + '?s=' + textToSearch + getPagingDetails(); 159} 160 161function getPagingDetails() { 162 let tab = $('.btn-ren--tabs-slim.active').attr('id'); 163 let _tab = 0; 164 165 switch (tab) { 166 case 'tab-pages': 167 _tab = 1; 168 break; 169 case 'tab-news': 170 _tab = 2; 171 break; 172 case 'tab-multimedia': 173 _tab = 3; 174 break; 175 case 'tab-documents': 176 _tab = 4; 177 break; 178 default: 179 _tab = 1; 180 break; 181 } 182 183 let params = '&pp=' + search_current_page 184 + '&l=' + search_items_per_page 185 + '&t=' + _tab 186 + '&pi=' + search_current_news 187 + '&pv=' + search_current_multimedia 188 + '&pd=' + search_current_document; 189 190 return encodeURI(params); 191} 192 193function searchMain() { 194 search_current_page = 1; 195 search_current_news = 1; 196 search_current_multimedia = 1; 197 search_current_document = 1; 198 199 let element = document.getElementById('ws_txt_search_global_principal'); 200 if (element) { 201 let textToSearch = element.value; 202 setOnRecentSearches(textToSearch); 203 204 setBrowserLocation(getSeachBase() + '&c=' + getSearchCategory()); 205 } 206} 207 208function getSearchCategory() { 209 let element = document.getElementsByClassName('tag-ren_special')[0]; 210 211 if (element === undefined) { 212 return '' 213 } 214 215 return encodeURI(element.getAttribute('id').replace('searchMainCat_', '')); 216} 217 218function searchByRecent(text) { 219 search_current_page = 1; 220 221 setBrowserLocation(encodeURI(__searchPageUrl) + '?s=' + escapeSearchTextToHTML(text) + encodeURI(getPagingDetails())); 222} 223 224function goToSearchPage(searchpage) { 225 let element = document.getElementById('ws_txt_search_global'); 226 if (element) { 227 let textToSearch = element.value.trim(); 228 229 // Store the search term in recent searches 230 setOnRecentSearches(textToSearch); 231 232 // Validate and sanitize the searchpage URL 233 let safeSearchPage = validateAndSanitizeSearchPage(searchpage); 234 if (safeSearchPage) { 235 // Properly URL-encode the search parameter (not HTML escape) 236 const encodedSearchText = encodeURIComponent(textToSearch); 237 238 // Construct the final URL and redirect 239 setBrowserLocation(safeSearchPage + '?s=' + encodedSearchText); 240 } else { 241 console.error("Invalid or unsafe searchpage URL. Redirection aborted."); 242 } 243 } 244} 245 246function validateAndSanitizeSearchPage(searchpage) { 247 // Ensure the searchpage is a valid relative path 248 if (typeof searchpage !== "string" || searchpage.trim() === "") { 249 console.error("Invalid searchpage URL: Empty or non-string input."); 250 return null; 251 } 252 253 // Must be a relative path starting with / 254 if (!searchpage.startsWith("/")) { 255 console.error("Invalid searchpage URL: Must start with /"); 256 return null; 257 } 258 259 // Prevent directory traversal 260 if (searchpage.includes("../") || searchpage.includes("..\\")) { 261 console.error("Invalid searchpage URL: Path traversal detected."); 262 return null; 263 } 264 265 // Ensure there are no protocol handlers or special characters 266 if (/[:?#&=]/.test(searchpage)) {
267 console.error("Invalid searchpage URL: Contains invalid characters."); 268 return null; 269 } 270 271 // Return the validated path 272 return searchpage; 273} 274 275 276function searchNextPage() { 277 search_current_page += 1; 278 279 searchNavigate() 280} 281 282function searchPreviousPage() { 283 search_current_page -= 1; 284 285 searchNavigate() 286} 287 288function searchNextImage() { 289 search_current_news += 1; 290 291 searchNavigate() 292} 293 294function searchPreviousImage() { 295 search_current_news -= 1; 296 297 searchNavigate() 298} 299 300function searchNextVideo() { 301 search_current_multimedia += 1; 302 303 searchNavigate() 304} 305 306function searchPreviousVideo() { 307 search_current_multimedia -= 1; 308 309 searchNavigate() 310} 311 312function searchNextDocument() { 313 search_current_document += 1; 314 315 searchNavigate() 316} 317 318function searchPreviousDocument() { 319 search_current_document -= 1; 320 321 searchNavigate() 322} 323 324function searchNavigate() { 325 setBrowserLocation(getSeachBase() + '&c=' + getSearchCategory()); 326} 327 328function setBrowserLocation(location) { 329 // Validate the location is a simple relative path 330 if (!location || typeof location !== 'string') { 331 console.error('Invalid location: empty or not a string'); 332 return; 333 } 334 335 // Reject absolute URLs or protocol-relative URLs 336 if (location.match(/^(?:[a-z]+:|\/\/)/i)) { 337 console.error('Invalid location: contains protocol or is protocol-relative'); 338 return; 339 } 340 341 // Remove any path traversal attempts 342 const sanitizedLocation = location.replace(/\.\.\//g, ''); 343 344 // Construct the full URL safely 345 const baseOrigin = document.location.origin; 346 const safeUrl = new URL(sanitizedLocation, baseOrigin).href; 347 348 // Optional: verify the URL still starts with our origin 349 if (!safeUrl.startsWith(baseOrigin)) { 350 console.error('Security error: URL would redirect outside origin'); 351 return; 352 } 353 354 // Perform the redirect 355 window.location.assign(safeUrl); 356} 357 358 359function setPageRecentSearches() { 360 let searchHistoryDivs = document.getElementsByClassName('search-history'); 361 362 if (searchHistoryDivs.length == 0) 363 return; 364 365 let searchHistoryDiv = searchHistoryDivs[0]; 366 let searchHistoryRowDiv = searchHistoryDiv.childNodes[1]; 367 let recentSearches = getRecentSearches(); 368 let index = 0; 369 370 const fragment = new DocumentFragment(); 371 372 if (recentSearches.length > 0) { 373 for (var i = 0; i < search_local_storage_cols; i++) { 374 addRecentSearchHistoryContainer(i, searchHistoryRowDiv); 375 376 for (var j = 0; j < search_local_storage_col_max; j++) { 377 if (index >= recentSearches.length) break; 378 let searchRecentText = unescapeHtml(recentSearches[parseInt(index)]); 379 addRecentSearchHistoryItem(searchRecentText, j, i); 380 381 index += 1; 382 } 383 } 384 385 document.querySelectorAll('[data-recent-search]').forEach(el => { 386 const linkText = el.getAttribute('data-recent-search'); 387 388 el.addEventListener('click', (e) => { 389 e.preventDefault() 390 searchByRecent(linkText) 391 }) 392 }); 393 } 394} 395 396function addRecentSearchHistoryItem(text, id, parentId) { 397 let parentList = $(`#search-history-list-${parentId}`) 398 $(unescapeHtml(liElementTag), { 399 id: `search-history-list-item-${parentId}-${id}`, 400 appendTo: parentList 401 }); 402 403 let parentItem = $(`#search-history-list-item-${parentId}-${id}`) 404 $(unescapeHtml(aElementTag), { 405 id: `search-history-list-item-url-${parentId}-${id}`, 406 href: "#", 407 text: text, 408 appendTo: parentItem 409 }).attr('data-recent-search', text); 410} 411 412function addRecentSearchHistoryContainer(id, parent) { 413 $(unescapeHtml(divElementTag), { 414 id: `search-history-container-${id}`, 415 "class": "col-12 col-sm-6 col-lg", 416 appendTo: parent 417 }); 418 419 let parentContainer = $(`#search-history-container-${id}`) 420 $(unescapeHtml(ulElementTag), { 421 id: `search-history-list-${id}`, 422 "class": "history-list d-flex flex-column gap-2 mb-2", 423 appendTo: parentContainer 424 }); 425} 426 427function setOnRecentSearches(text) { 428 let recentSearches = getRecentSearches(); 429 if (recentSearches.length >= search_local_storage_max) { 430 removeOldestFromLocalStorage(search_local_storage_prefix); 431 } 432 addToLocalStorage(search_local_storage_prefix, unescapeHtml(text)); 433} 434 435function getRecentSearches() { 436 return getAllFromLocalStorage(search_local_storage_prefix); 437} 438 439function escapeSearchTextToHTML(str) { 440 let result = str.replace(/[&<>"'\\/]/g, function (char) { 441 switch (char) { 442 case '&': 443 return '&'; 444 case '<': 445 return '<'; 446 case '>': 447 return '>'; 448 case '\\': 449 return '''; 450 case '/': 451 return '/'; 452 default: 453 return char; 454 } 455 }); 456 457 return result.replace('&', "%26"); 458} 459 460function unescapeHtml(str) { 461 var doc = new DOMParser().parseFromString(str, "text/html"); 462 return doc.documentElement.textContent; 463}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.