8. AJAX İşleyicisi
DLE 21.0, tüm AJAX isteklerini tek bir yönlendiriciden geçirir. Bu, eklenti yazarken işinizi kolaylaştırır: dosyanızı doğru yere koyup modül adını doğru verirseniz DLE onu kendisi bulur.
İstek biçimi
mod parametresi engine/ajax/<mod>.php dosyasına karşılık gelir.
DLE, yönlendirmeyi engine/ajax/controller.php içinde yapar.
Yönlendirici ne yapar?
// engine/ajax/controller.php — özet
header("Content-type: text/html; charset=utf-8");
$mod = str_replace(chr(0), '', (string)$_REQUEST['mod']);
$mod = trim( strtolower(strip_tags( $mod )) );
$mod = preg_replace( "/\s+/ms", "_", $mod );
$mod = str_replace( "/", "_", $mod );
$mod = preg_replace( "/[^a-z0-9\_\-]+/mi", "", $mod );
// … oturum, dil, üye ve kategori verileri hazırlanır …
if ( $mod != 'controller' AND file_exists( DLEPlugins::Check(ENGINE_DIR . '/ajax/' . $mod . '.php') )) {
include_once (DLEPlugins::Check(ENGINE_DIR . '/ajax/' . $mod . '.php'));
} else {
header("HTTP/1.0 404 Not Found");
die( "Module not found!" );
}
Buradan çıkan sonuçlar:
| Konu | Sonuç |
|---|---|
| Modül adı | Küçük harfe çevrilir, boşluklar _ olur, / _
olur, geçersiz karakterler atılır. Adı ASCII ve küçük harf tutun. |
controller adı |
Kullanılamaz — controller.php kendini çalıştırmaz. |
| Yükleniyor mu? | Evet DLEPlugins::Check() ile —
yani AJAX dosyaları da yamalanabilir. |
| Yanıt başlığı | Her zaman text/html; charset=utf-8. JSON döndürseniz
bile başlık değişmez. |
| Bulunamazsa | 404 + Module not found! |
text/html başlığı JSON'u geçersiz kılmaz, ama Content-Type: application/json
bekleyen kütüphaneler bunu metin olarak alır. jQuery'nin
dataType: 'json' seçeneği metni ayrıştırdığı için sorun çıkmaz; başka bir
istemci kullanıyorsanız yanıtı elle ayrıştırmanız gerekebilir.
İki modül ailesi
Yönlendirici, modülün yönetim mi yoksa ön yüz mü olduğunu belirler ve ona göre farklı dosyalar yükler:
| Yönetim modülleri | Ön yüz modülleri | |
|---|---|---|
| Liste | adminfunction, antivirus, clean,
upload, find_relates, find_tags,
keywords, newsletter, rebuild,
rss, sitemap, templates,
updates, plugins, newsletter_templates,
oembed |
Diğerleri: comments, pm, rating,
favorites, poll, calendar,
search, profile, registration,
quote, … |
| Yüklenen fonksiyonlar | engine/inc/include/functions.inc.php |
engine/modules/functions.php |
| Dil dosyası | adminpanel.lng |
website.lng |
| Ülke/engelleme denetimi | Panel için tanımlı allowed_panel_country / declined_panel_country |
Site için tanımlı allowed_country / declined_country |
{"error":true, "content":"banned"}
Kritik uyarı: merkezî CSRF koruması YOK
user_hash içerdiğini kontrol etmez.
Her AJAX işleyicisi bu denetimi kendi içinde yapar. Bunu atlarsanız işleyiciniz
siteler arası istek sahteciliğine (CSRF) açık olur.
DLE'nin kendi işleyicileri bunu şu kalıpla yapar
(engine/ajax/commentssubscribe.php):
if( !isset($_REQUEST['user_hash']) OR !$_REQUEST['user_hash'] OR $_REQUEST['user_hash'] != $dle_login_hash ) {
echo "{\"error\":true, \"errorinfo\":\"{$lang['error_sec_code']}\"}";
die();
}
$dle_login_hash, yönlendirici tarafından
sha1(SECURE_AUTH_KEY . $_SERVER['HTTP_USER_AGENT']) biçiminde üretilir ve
ön yüzde JavaScript'e dle_login_hash olarak aktarılır.
Bir işleyicinin iskeleti
Her AJAX dosyası şu sırayla başlar — DLE'nin kendi dosyalarıyla birebir aynı:
// engine/ajax/benim-modulum.php
if(!defined('DATALIFEENGINE')) {
header( "HTTP/1.1 403 Forbidden" );
header ( 'Location: ../../' );
die( "Hacking attempt!" );
}
// 1) Gerekli koşullar sağlanıyor mu?
if ( !$config['allow_benim_ozellik'] ) {
echo "{\"error\":true, \"errorinfo\":\"Bu özellik kapalı.\"}";
die();
}
// 2) CSRF denetimi (ZORUNLU)
if( !isset($_REQUEST['user_hash']) OR !$_REQUEST['user_hash'] OR $_REQUEST['user_hash'] != $dle_login_hash ) {
echo "{\"error\":true, \"errorinfo\":\"Güvenlik kodu geçersiz.\"}";
die();
}
// 3) İşi yap
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
if ( !$id ) {
echo "{\"error\":true, \"errorinfo\":\"Eksik parametre.\"}";
die();
}
$db->query("UPDATE " . PREFIX . "_post SET my_flag='1' WHERE id = '{$id}'");
// 4) Yanıt ver
echo json_encode(array('success' => true, 'message' => 'Kaydedildi.'));
die();
Yanıt biçimi
DLE'nin kendi işleyicilerinde iki yaygın kalıp vardır. Hangisini seçerseniz seçin tutarlı olun ve JavaScript tarafını ona göre yazın:
| Kalıp | Örnek | JS tarafı |
|---|---|---|
| JSON nesnesi | echo json_encode(array('success' => true, 'content' => $html)); |
dataType: 'json' |
| Düz metin durum kodu | die('ok'); / die('error'); |
Yanıtı doğrudan karşılaştırın |
JavaScript tarafı: hazır yardımcılar
public/js/dle_js.js içinde gelen ve tema kodu yazmadan kullanabileceğiniz
araçlar:
| Fonksiyon | Ne yapar |
|---|---|
ShowLoading() / ShowLoading("metin") | Yükleniyor göstergesi açar. |
HideLoading() | Göstergeyi kapatır. |
DLEPush.info(mesaj) | Başarı/onay bildirimi (yeşil). |
DLEPush.warning(mesaj) | Uyarı bildirimi. |
DLEPush.error(mesaj) | Hata bildirimi. |
DLEconfirm(metin, başlık, callback) | Onay penceresi. |
DLEconfirmDelete(metin, başlık, callback) | Silme onayı (kırmızı düğme). |
DLEalert(metin, başlık) | Bilgi penceresi. |
DLEprompt(...) | Girdi penceresi. |
DLEPush.success() YOKTUR
İnternette sık geçer ama DLE 21.0 dosyalarında DLEPush'un yalnızca
info, warning ve error metotları vardır. Başarı
mesajı için DLEPush.info() kullanın.
Çağrı örneği:
ShowLoading();
$.post(dle_root + "index.php?controller=ajax&mod=benim-modulum", {
id: haber_id,
user_hash: dle_login_hash
}, function (cevap) {
HideLoading();
if (cevap.success) {
DLEPush.info(cevap.message);
} else {
DLEPush.error(cevap.errorinfo);
}
}, "json");
dle_login_hash global değişkenini unutmayın
Bu değer ön yüzde hazır gelir. Form veya AJAX verisine eklemeyi unutursanız isteğiniz
CSRF denetiminden geçemez ve error döner.
Tema dosyalarınızı yüklemek
AJAX işleyicinizde tema dosyası (CSS/JS) kullanmanız gerekiyorsa, bunları doğrudan
yazdırmak yerine DLE'nin bağımlılık dizilerine ekleyin. Panel tarafında
$js_array ve $css_array değişkenleri bu işe yarar; ön yüzde
yönlendirici aynı dizileri kullanır.
AJAX işleyicisi kontrol listesi
- Dosya
engine/ajax/<kucuk-harf-ascii>.php. - En başta
DATALIFEENGINEdenetimi var. user_hashdenetimi var (atlanmadı).- Gerekli koşullar (config/grup izinleri) kontrol ediliyor.
- Kullanıcı girdileri
intval()/safesql()ile süzülüyor. - Her hata yolu bir yanıt döndürüp
die()ediyor (sessiz çıkış yok). - Yanıt biçimi JavaScript tarafıyla uyuşuyor.
- Kullanıcıya gösterilen tüm çıktı
htmlspecialchars()ile kaçırılmış.
İlgili sayfalar: Güvenlik Kontrol Listesi · Veritabanı ve Veri.