跳到主要內容

發表文章

目前顯示的是 2026的文章

修正 XOOPS 2.7 儲存頁尾註腳 HTML 會被自動過濾為純文字的問題

今天無意間又發現 XOOPS 2.7的一個BUG問題,就是儲存頁腳的資訊區塊,原本(XOOPS2.5.11)都還能支援HTML格式,現在貼入內容會被自動清除為純文字格式,這不處理會死人的呢!!頁腳聯絡資訊,網站資訊,還有AA標章,連CSS都沒辦法用,一堆HTML要放的,變成純文字能交差嗎。 經追查資料庫config存進去就已經被過濾成純文字了,研判因該是在儲存端的Xoops安全機制過濾的,於是再反查Xoops的modules/system/admin.php 最後在這裡找到 modules\system\admin\preferences 用筆記本打開找到約第439行 // Detect this and explicitly set an empty array instead. 吧下面整段註解掉 /* $multiFormTypes = ['select_multi', 'group_multi', 'user_multi', 'theme_multi']; if (in_array($formType, $multiFormTypes, true) && !Request::hasVar($confName, 'POST')) { $new_value = []; } else { $new_value = Request::getVar($confName, $config->getVar('conf_value'), 'POST'); }*/ 替換為 //修改儲存頁腳footer會被自動過成濾純文字的問題 $multiFormTypes = ['select_multi', 'group_multi', 'user_multi', 'theme_multi']; if (in_array($formType, $multiFormTypes, true) && !Request::hasVar($...

CSS LOGO 描邊陰影字工法(替換原 filter: drop-shadow)用法,解決行動瀏覽異常消電原問題(觸發 GPU 合成層)

之前寫過一篇【 用CSS做出來一個文字漸層+文字白框+文字陰影的LOGO區塊,CSS最終解法並符合無障礙 】的工作心得,但經過多次實際驗證,filter: drop-shadow方法雖然較為美觀,但在行動瀏覽或是平板,容易觸發 GPU 合成層,導致版面異常(畫面上下空白),裝置發燙等耗電等問題,因此經改良後,改用CSS LOGO 描邊陰影字工法能維持與原本 filter: drop-shadow相同的效果,且手機平版不會異常,方法如下: 以下是使用-webkit-text-stroke/text-shadow做出來的文字效果,幾乎能90%還原PSD設計效果 文字的PHP常數增加data-storke設定 define('_THEME_LOGO_02','<div class="logo_01_box" aria-hidden="true" tabindex="-1" data-storke="桃園市" >桃園市</div><div class="logo_02_box" aria-hidden="true" tabindex="-1" data-storke="快樂" >快樂</div><div class="logo_03_box" aria-hidden="true" tabindex="-1" data-storke="國民小學" >國民小學</div>'); 注意: aria-hidden="true":視覺文字不給讀報軟體讀。 - tabindex="-1":避免視覺文字進入 TAB 流。 data-storke:提供 CSS content:attr(data-storke); 使用。 外層已有可讀 aria-label 或 sr-only,不要讓同一段校名被讀兩次。 CSS 核心寫法 #toplogobox{ position:relative; width:980p...

修正 XOOPS 2.7 profile 模組編輯欄位時出現 Incorrect column name '' 問題

今天測試 XOOPS 2.7 的 profile 模組時,無意間發現後台欄位編輯有一個問題。 操作路徑:後台 → Profile 模組 → 欄位 → 編輯 只要修改任意一項後送出,就會出現錯誤: Errors field_name 為必填項 Incorrect column name '' MySQL 除錯訊息會看到類似這段: ALTER TABLE profile_profile ADD  varchar(255) NULL 一開始看起來很像資料表壞掉,因為 SQL 竟然要新增一個空白欄位名稱。但後來追程式才發現,真正原因不是資料表問題,而是表單送出時沒有把既有欄位的 id 傳回去。 XOOPS 2.7 的 modules/profile/admin/field.php 在儲存時會從 POST 讀取欄位 id: $fieldId = Request::getInt('id', 0, 'POST'); 如果 POST 沒有收到 id,系統就會誤判成「新增欄位」。但因為目前其實是在編輯既有欄位,表單中沒有 field_name 輸入框,最後就變成欄位名稱是空字串,進而產生: ADD  varchar(255) 修復方式 用文字編輯器打開:modules/profile/include/forms.php 找到 profile_getFieldForm() 裡建立表單的位置,大約在前段: $form = new XoopsThemeForm($title, 'form', $action, 'post', true); 在下方加入: if (!$field->isNew()) { $form->addElement(new XoopsFormHidden('id', $field->getVar('field_id'))); } 也就是讓所有「編輯既有欄位」的表單,都固定送出 hidden id。 修正後,送出欄位設定時,field.php 就能正常收到 POST id,不會再誤判成新增欄位,也不會產生空欄位名稱的 SQL。 修正後結果 經實測: - profile 欄位可正常編輯 - 欄位設定可正常儲存 - 不再出現 field_name ...

XOOPS 2.7 升級筆記:Smarty 4 不支援 <{php}> 的解決方法

 XOOPS 2.7 全面升級到 Smarty 4 後,舊佈景或舊模組最容易炸掉的地方,就是樣板裡的 `<{php}>...<{/php}>`。 原因很單純:Smarty 4 已經不支援在樣板中直接執行 PHP。也就是說,舊寫法如果還把 PHP 邏輯塞在 `.tpl` 裡,升級後就會出現 unknown tag、白畫面或 SmartyCompilerException。 目前比較穩的解法,不是去 hack Smarty,也不是讓 Smarty 重新開放任意 PHP,而是把原本散落在樣板中的 PHP 程式碼收回 PHP 檔案,整理成 function,再用 `$tpl->registerPlugin()` 註冊成 Smarty 標籤,最後在樣板中用新標籤取代原本的 `<{php}>`。 簡單說: 舊寫法: .tpl 直接寫 <{php}> PHP CODE <{/php}> 新寫法: PHP 檔建立 function → registerPlugin 註冊成 Smarty function → .tpl 改用 <{php_channel}> 這樣效果接近原本 `<{php}>`,但執行入口變乾淨,也比較符合 Smarty 4 的規則。 修改方法如下說明: 一、建立相容函式檔 建議先建立一個 PHP 檔,專門收納原本樣板裡的流浪 PHP,例如: modules/模組ID/function/tpl_smarty_compat.php 示例: <?php //Smarty 4 樣板流浪 PHP 收容區 function register_smarty_compat($tpl=""){ if(empty($tpl) || !is_object($tpl)) return; if(!method_exists($tpl,'registerPlugin')) return; static $registered=array(); $tplid=function_exists('spl_object_id') ? spl_object_id($tpl) : spl_object_hash($tpl); if(!empty($regist...

Apache 網站存取與嵌入防護設定(敏感檔案、目錄瀏覽、iframe 防護)

話說時間過得真快,轉眼間又收到上半年度局端的伺服器「弱點管制表」通報,其中當然免不了那些PHP/Apache需要升級項目,但本次多了三個新弱點項目,做個紀錄日後就能SOP處理! 弱點名稱:備份檔案洩漏 弱點概述:It is possible to retrieve file backups from the remote web server. 弱點名稱:Web 伺服器的目錄/資料夾可被瀏覽 弱點概述:Some directories on the remote web server are browsable. 弱點名稱:Web 應用程式具有點擊劫持(ClickJacking)的弱點 弱點概述:The remote web server may fail to mitigate a class of web application vulnerabilities. 這三個弱點可以一次解決,只需要找到 HTTPS vhost,也就是 <IfModule mod_ssl.c> 裡的 <VirtualHost *:443>。 該檔案通常由 certbot 自動產生,檔案名稱多為:000-default-le-ssl.conf(通常位於 sites-available 資料夾中,並連結到 sites-enabled 啟用) sudo nano /etc/apache2/sites-available/000-default-le-ssl.conf 打開編輯 <IfModule mod_ssl.c> <VirtualHost *:443> 略........................ ServerAdmin webmaster@localhost DocumentRoot /var/www/html #防護設定加在DocumentRoot 後面 #這段解決Web 伺服器的目錄/資料夾可被瀏覽問題 <Directory /var/www/html> Options -Indexes AllowOverride All Require all granted </Directory> #這段解決備份檔案洩漏 <FilesMatch "(?i)(~$|\.bak$|\.old$|\.or...

用CSS的@font-face自訂網站字體的方法

由於原本Google提供的@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400&display=swap'); 會有阻塞渲染問題,導致 CSS 檔案載入變慢,瀏覽器必須先下載完 CSS,再解析到 @import,再去下載字體,這會增加網頁出現「空白字體(FOIT)」的時間。 基於效能優化,2026年建議改用CSS的@font-face自訂字體方法,也就是把字體放在自己的伺服器讓用戶載入網站字形,效能比@import方法要好,穩定性也更高,以下是完整建立@font-face方法說明。 1、先去fonts Google選擇需要的開源字體並下載 https://fonts.google.com/ 2、下載回來後解壓縮字形檔,因該是.ttf格式,建議改成 woff2格式會「比較穩」 .woff2 是現代瀏覽器標準壓縮過(小很多)Google Fonts 主力格式,以下網站可以更改字形副檔名格式 https://cloudconvert.com/ 點選Select File再選擇From my computer 選擇電腦中要改檔案的.ttf上傳後,選擇改為 woff2 Convert後等轉換完成,將.woff2 下載回來 3、在自己網站根目錄建一個fonts資料夾,然後吧字形檔貼入(例如cwTeXHei.woff2),接者再fonts資料夾中建一個.htaccess 貼上以下防熱連設定,避免字形資源被人拿去白漂 RewriteEngine On # 只處理字型檔 RewriteCond %{REQUEST_URI} \.(woff2|woff|ttf|otf)$ [NC] # 空 referer 放行:直接開檔、本地測試、某些瀏覽器情境 RewriteCond expr "%{HTTP_REFERER} == ''" RewriteRule .* - [L] # localhost / 127.0.0.1 放行:只在目前主機就是本地端時成立 RewriteCond %{REQUEST_URI} \.(woff2|woff|ttf|otf)$ [NC] RewriteCond %{HTTP_HOST} ^(localhos...

做一個簡單CK編輯器符合無障礙AA的設定方法!!

由於無障礙AA中規定對於A元素,或是iframe都需要有title語意說明,若是LINK外連還需要加上另開新視窗說明,如果用CK編輯器複製貼上,來源端就帶有連結但USER又沒設title就會被列為缺失,假使只是用於小型的說明用途欄位,用以下的CK設定參數就可以解決了! CKEDITOR.replace(" t extarea的id ", { height: 200, //高度 //toolbar參數,簡單的basicstyles及paragraph兩個插件(可自行增加) toolbar: [ { name: 'basicstyles', items: [ 'Bold', 'Italic', '-', 'RemoveFormat' ] }, { name: 'paragraph', items: [ 'NumberedList', 'BulletedList' ] } ], removePlugins: 'link,iframe,flash,forms', forcePasteAsPlainText: true }); 重點說明 removePlugins: 'link,iframe,flash,forms', 直接禁止:link,iframe,flash,forms類型的物件存在編輯器 forcePasteAsPlainText: true 貼上時,只保留純文字,不要任何格式 例如複製這一段有帶超連結的內容 貼到CK編輯框後,自動變成純文字格式,USER貼文也就不會有無障礙缺失的問題 這方法適合只需要簡單文字的編輯框,像是簡易討論區或是留言板,以及公開資料說明等,再必須符合無障礙AA規範下,用這方法能解決。 以上工作心得撰寫,有需要的朋友參考看看💁💁 工作心得撰寫: 徐嘉裕 Neil hsu

修正Xoops2.5.11佈景樣板system_search.tpl「顯示全部結果查」查詢失效的方法

今天無意中使用xoops的搜尋功能,結果發現資料多於預設數量時會被隱藏,但點選「顯示全部結果」卻查沒有半筆資料!!先釐清是不是佈景吃掉了showall變數,經確認換回官方的xswatch4佈景也是一樣結果,只能動手來找bug了,當然最先懷疑的一定是search.php,經過徹底查詢一路追到 case 'showall': //略.............. $xoopsTpl->appendByRef('results_arr', $results_arr); var_dump($results_arr);exit; //輸出陣列 確認$results_arr整包是有被輸出的,但樣板端卻沒顯示,這樣問題就很清楚了,是樣板端吃掉了$results_arr,接下來就來查樣板 ../themes/您的佈景id/modules/system/system_search.tpl (如果沒有去xswatch4整包拆回來) 發現$results_arr迴圈根本沒被輸出 <{foreach item=data from=$results_arr|default:null}> 略............ <{/if}> 這下傷腦筋了,PHP有給值,但到樣板卻消失,還好最後在前段找到這個兇手 <{if isset($nomatch) && $nomatch == true}> 因該是case 'showall':沒有給$nomatch = true 所以這一段才會無效,但如果改php檔之後升級xoops又會被覆蓋掉,那只能由樣板端處理 用筆記本開system_search.tpl,搜尋 <{if isset($nomatch) && $nomatch == true}> 替換成  <{if !empty($results_arr) || (isset($nomatch) && $nomatch != true)}> 這樣就能讓「顯示全部結果」恢復正常了(如下圖) 測試連結: https://neodw.com/search.php?query=%E7%B6%B2%E7%AB%99%E8%A8%AD%E8%A8%88&m...

Xoops免費佈景:neilambilight3.6正式版釋出-可兼容TAD模組,佈景設計開發:徐嘉裕Neil hsu

歷經一年多持續開發與優化,neilambilight 3.6 正式版正式登場。本次改版不僅全面強化無障礙AA支援,更導入尼爾自研的「Neil_ISP v2.0 分散式爬蟲攻擊智能防禦安全套件」,大幅提升網站整體安全與流量防護能力。 同時針對介面設計與操作體驗進行全面升級,加入aa-flow 自流動排版機制,可隨瀏覽器縮放自動調整版面,最高支援至400%,並達成TAD模組全面兼容,兼顧美觀、實用、安全、相容與無障礙等多重需求。 本次改版可說是一次從核心到體驗的全面進化,歡迎下載體驗全新升級的 neilambilight! 下載neilambilight3.6正式版       neilambilight3.6佈景展示站 新增與調整重點 無障礙 AA 全面升級 支援 NVDA 讀報、鍵盤操作優化、焦點管理強化 aa-flow 自流動版面(100%~400% 自適應) AWD 自適應流動排版系統 200% 自動單欄重排 250% / 300% / 400% 完整流動支援 全站 CSS REM 化 Neil_ISP v2.0 安全防護系統 蜜罐誘捕爬蟲 行為判斷封鎖 流量防護與 LOG 管理整合 TAD 模組全面兼容 自動補齊 JS / CSS 依賴 修正 tpl 衝突 Neil / TAD 智能分流機制 介面與操作體驗優化 新版 UI 設計(符合現代與 AA 安全色) 漢堡選單 / 浮動選單優化 字級切換與操作回饋強化 實用功能強化 短網址生成與還原功能 JSON-LD 結構化資料(SEO 強化) 表單與登入流程無障礙優化 GTM、AJAX、安全驗證補強     無論是視覺呈現、操作流暢度,或無障礙設計,neilambilight 3.6 都帶來全面性的升級體驗。 如果您正在使用 XOOPS 2.5.11 正式版,誠摯邀請您下載安裝,親自感受新一代佈景系統所帶來的穩定性與效率提升。 neilambilight3.6更新項目 修正無障礙NVDA讀報系統無法辨識JS的Enter事件,導...

使用Xoops的preload機制做fsockopen非同步幕後執行不占用前端資源

其實會想用 fsockopen 做非同步幕後執行,主要是因為客戶要開發自動批次下載Google雲端硬碟及自動建立檔案功能,如果用以往的活人撞針方法,觸發執行的那個ip會因為自動執行畫面整個延遲卡死(UX死當),必須改用非同步方式來解決 (瀏覽跟執行層分開) ,經過測試fsockopen確實能開一個新的HTTP請求至目標腳本然後斷線不理 (非同步) ,腳本自動以Web Server中獨立request執行程序,完全不影響前端頁面瀏覽不延遲,能優化UX體驗,不需要用活人獻祭了(改幕後執行),以下是框架及心得分享 要建立fsockopen前需要先使用Xoops的preload機制,preload是XOOPS提供的全域事件機制,可在每次request的特定生命週期節點(如 footer)插入自訂邏輯,使所有頁面都能觸發指定行為,換句話說在模組中執行preload的腳本,Xoops全體頁面都能被觸發事件(全域事件機制),所以拿來當作fsockopen的執行footer非常適合。 preload = XOOPS 全域事件鉤子(Hook) XOOPS 啟動流程中 → 每個 request 都會觸發 preload → 依事件執行(你用的是 Footer) 建立preload方法 先在xoops模組根目錄建立一個preloads,在置入一個core.php檔案 例如:my_modules/preloads/core.php 然後加入以下代碼 <?php class NeilalbumCorePreload extends XoopsPreloadItem { public static function eventCoreFooterStart($args) { //eventCoreFooterStart 所有頁面 / 在輸出footer前 /都會觸發 async_trigger(); } } function async_trigger() { global $xoopsModuleConfig,$xoopsModule,$isAdmin; //做一個$token $secret_id="rEDBzCyHEJ7Yv32ie5JPyB0WmKP9caeDPbkpfc1L"; //可改成自己要的雜奏碼 $ts = time(); $tok...

好用的Chrome瀏覽器批次下載套件DownThemAll!推薦-終於不用一個一個下載了!!

建置網站最怕遇到的就是舊資料移轉,有時候檔案數量龐大,一個一個下載手都酸了,經查詢發現有更好的方法能決這問題,這裡將經驗分享給大家!! 例如這一個頁面,有60幾個PDF檔要下載,一個一個下載完天都亮了!!這時候真的需要借用工具的力量來幫我們自動化處理!! 推薦一個好用的Chrome瀏覽器批次下載套件DownThemAll! 先點Chrome瀏覽器最右上方的三個橫點,打開選單,找到「擴充功能」再選擇子選單「前往Chrome應用程式商店」 然後輸入關鍵字「DownThemAll」找到套件後安裝起來,接下來前往要下載檔案的頁面,點選右上方的工具列,找到DownThemAll,點選打開! 選擇DownThemAll打開設定選單,選擇DownThemAll,透過篩選器選擇設定 完成後按下載,只需要enter到底就能下載完成,檔案預設會放在C:\XXXX\XXXXX\Downloads\downthemall 目錄中 或是選擇OneClick也能下載, 一樣只需要鍵盤enter一直按到叮咚一聲,檔按下載就完成,至於為什麼要用OneClick,主要是他能模擬人工點擊,如果用批次,若是檔案中又包有iframe就會被下載兩次,或是更多次,因此OneClick是個不錯的決方法,經實測頁面60個pdf檔批次下載回來也是60個,數量正確檔按無缺損,這套件確實能解決大量檔案下載問題,有需要的朋友可以參考看看!! 備註:OneClick 模式並非解析整頁資源,而是僅擷取使用者可見之下載連結,等同模擬人工點擊流程,因此可避免因 iframe 或預覽機制造成的重複下載問題。 工作心得撰寫: 徐嘉裕 Neil hsu