WordPress’te Yükleme Dosya Türlerini Kısıtlama veya Genişletme
WordPress sitenize dosya yüklerken “Bu dosya türüne izin verilmiyor” hatasıyla karşılaştıysanız, yalnız değilsiniz. Bu durum özellikle WooCommerce mağazalarında, portföy sitelerinde veya müşterilere özel yükleme alanları sunan projelerde sıkça yaşanır. WordPress, güvenlik nedeniyle varsayılan olarak belirli dosya türlerini kabul eder, geri kalanını reddeder. Bazen bu listeye yeni türler eklemek, bazen de güvenlik açısından bazı türleri kısıtlamak gerekir. Bu yazıda functions.php üzerinden bu işlemlerin nasıl yapılacağını, gerçek senaryolarla birlikte ele alacağız.
WordPress’in Varsayılan Dosya Türü Sistemi Nasıl Çalışır
WordPress, yükleme işlemlerini wp_check_filetype_and_ext() ve upload_mimes filtresi üzerinden yönetir. Sistem, yüklenen dosyanın MIME türünü kontrol eder ve bu tür izin verilen listede yoksa yüklemeyi reddeder.
Varsayılan olarak WordPress şu kategorilerdeki dosyalara izin verir:
- Görseller: jpg, jpeg, png, gif, webp, ico, svg (kısıtlı)
- Belgeler: pdf, doc, docx, xls, xlsx, ppt, pptx
- Ses: mp3, wav, ogg, m4a
- Video: mp4, mov, avi, wmv, flv
- Arşivler: zip, tar, gz, rar (bazı kurulumlar)
Ancak .svg, .webp (eski sürümlerde), .json, .xml, .stl, .epub gibi türler ya hiç desteklenmez ya da sorunlu çalışır. İşte burada functions.php devreye giriyor.
Neden functions.php Üzerinden Yapmalıyız
Bazı sysadmin arkadaşlar bu işi doğrudan WordPress admin panelinden “Allowed File Types” ayarlarıyla yapmaya çalışır. Ama bu ayarlar her zaman yeterli değildir ve bazı hostingler sunucu tarafında ek kısıtlamalar uygular. functions.php üzerindeki çözümler şu avantajları sunar:
- Tema veya plugin güncellemelerinden bağımsız çalışır (child theme kullanıyorsanız)
- Sürüm kontrolüne (Git) kolayca dahil edilebilir
- Rol bazlı kısıtlama yapılabilir
- Debug ve loglama eklenebilir
Önemli Not: Bu kodları mutlaka child theme’inizin functions.php dosyasına ekleyin. Ana tema güncellendiğinde değişiklikleriniz silinmez.
Temel Kullanım: upload_mimes Filtresi
En basit yöntem upload_mimes filtresini kullanmaktır. Bu filtre, WordPress’in kabul ettiği MIME türlerinin listesini döndürür ve biz bu listeyi manipüle edebiliriz.
Yeni Dosya Türü Eklemek
// functions.php - Yeni dosya türleri eklemek
function sysadmin_izin_verilen_dosya_turleri( $mimes ) {
// SVG dosyalarına izin ver
$mimes['svg'] = 'image/svg+xml';
$mimes['svgz'] = 'image/svg+xml';
// JSON dosyalarına izin ver
$mimes['json'] = 'application/json';
// XML dosyalarına izin ver
$mimes['xml'] = 'text/xml';
// Yazı tipi dosyalarına izin ver
$mimes['woff'] = 'font/woff';
$mimes['woff2'] = 'font/woff2';
$mimes['ttf'] = 'font/ttf';
$mimes['eot'] = 'application/vnd.ms-fontobject';
// EPUB e-kitap formatı
$mimes['epub'] = 'application/epub+zip';
return $mimes;
}
add_filter( 'upload_mimes', 'sysadmin_izin_verilen_dosya_turleri' );
Belirli Dosya Türlerini Kısıtlamak
Bazen tam tersi gerekir. Örneğin paylaşımlı bir WordPress sitesinde editör rolündeki kullanıcıların PHP, JavaScript veya çalıştırılabilir dosya yüklemesini engellemek isteyebilirsiniz.
// functions.php - Tehlikeli dosya türlerini kaldır
function sysadmin_tehlikeli_dosya_turlerini_kaldir( $mimes ) {
// PHP ve benzeri çalıştırılabilir dosyaları kaldır
unset( $mimes['php'] );
unset( $mimes['php3'] );
unset( $mimes['php4'] );
unset( $mimes['php5'] );
unset( $mimes['phtml'] );
// JavaScript dosyalarını kaldır
unset( $mimes['js'] );
// HTML dosyalarını kaldır (XSS riski)
unset( $mimes['htm'] );
unset( $mimes['html'] );
// Flash dosyalarını kaldır (artık kullanılmıyor ama yine de)
unset( $mimes['swf'] );
return $mimes;
}
add_filter( 'upload_mimes', 'sysadmin_tehlikeli_dosya_turlerini_kaldir' );
Gerçek Dünya Senaryosu 1: WooCommerce Dijital Ürün Mağazası
Bir e-ticaret müşterisi için WooCommerce üzerinde dijital ürün satışı kuruyordunuz. Müşteri PDF, EPUB, MP3 ve özel .lpkg uzantılı lisans paketi dosyaları satmak istiyor. Varsayılan WordPress bu dosyaların bir kısmını reddediyor.
// functions.php - WooCommerce dijital ürün mağazası için özel MIME tipleri
function woo_dijital_urun_mime_turleri( $mimes ) {
// E-kitap formatları
$mimes['epub'] = 'application/epub+zip';
$mimes['mobi'] = 'application/x-mobipocket-ebook';
$mimes['azw'] = 'application/vnd.amazon.ebook';
// Ses formatları (podcast, müzik)
$mimes['flac'] = 'audio/flac';
$mimes['aac'] = 'audio/aac';
$mimes['m4b'] = 'audio/mp4';
// Özel uygulama formatları
$mimes['lpkg'] = 'application/octet-stream';
$mimes['dmg'] = 'application/x-apple-diskimage';
$mimes['apk'] = 'application/vnd.android.package-archive';
// CAD ve tasarım dosyaları
$mimes['dwg'] = 'application/acad';
$mimes['dxf'] = 'application/dxf';
$mimes['stl'] = 'model/stl';
return $mimes;
}
add_filter( 'upload_mimes', 'woo_dijital_urun_mime_turleri' );
Bu kodu ekledikten sonra WooCommerce ürün sayfasından bu dosyaları indirilebilir ürün olarak ekleyebilirsiniz.
Gerçek Dünya Senaryosu 2: Rol Bazlı Kısıtlama
Kurumsal bir WordPress sitesi yönetiyorsunuz. İçerik editörleri var, muhabirler var, admin var. Editörlerin sadece görsel yükleyebilmesini, muharrirlerin belge de ekleyebilmesini, yalnızca adminlerin her şeyi yükleyebilmesini istiyorsunuz.
// functions.php - Kullanıcı rolüne göre farklı MIME izinleri
function rol_bazli_mime_kisitlama( $mimes ) {
$kullanici = wp_get_current_user();
// Admin ve editor rolü için kısıtlama yok
if ( current_user_can( 'administrator' ) ) {
// SVG gibi özel türleri de ekle
$mimes['svg'] = 'image/svg+xml';
$mimes['json'] = 'application/json';
$mimes['xml'] = 'text/xml';
return $mimes;
}
// Muharrir (author) rolü: görseller + belgeler
if ( current_user_can( 'author' ) ) {
$izinli_turler = array(
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'webp' => 'image/webp',
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
);
return $izinli_turler;
}
// Contributor ve subscriber: sadece görseller
if ( current_user_can( 'contributor' ) || current_user_can( 'subscriber' ) ) {
$izinli_turler = array(
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'webp' => 'image/webp',
);
return $izinli_turler;
}
return $mimes;
}
add_filter( 'upload_mimes', 'rol_bazli_mime_kisitlama' );
wp_check_filetype_and_ext ile Gelişmiş Kontrol
WordPress 4.7.1’den itibaren güvenlik güncellemesiyle birlikte sistem daha katı hale geldi. Özellikle SVG gibi bazı dosya türleri upload_mimes filtresine eklense bile hata verebiliyor. Bunun sebebi dosya içeriğinin gerçek MIME türüyle uyuşup uyuşmadığını kontrol eden ikinci bir mekanizmanın devreye girmesi.
// functions.php - Gelişmiş dosya türü doğrulama (SVG ve benzeri sorunlu türler için)
function gelismis_dosya_turu_dogrulama( $data, $file, $filename, $mimes ) {
// Eğer WordPress zaten bir MIME tipi belirlediyse dokunma
if ( ! empty( $data['ext'] ) && ! empty( $data['type'] ) ) {
return $data;
}
// Dosya uzantısını al
$wp_file_type = wp_check_filetype( $filename, $mimes );
$ext = $wp_file_type['ext'];
$type = $wp_file_type['type'];
// SVG için özel kontrol
if ( 'svg' === $ext ) {
// SVG içeriğini okuyup gerçekten SVG mi diye kontrol et
$dosya_icerigi = file_get_contents( $file );
if ( false !== strpos( $dosya_icerigi, '<svg' ) ||
false !== strpos( $dosya_icerigi, '<?xml' ) ) {
$data['ext'] = 'svg';
$data['type'] = 'image/svg+xml';
$data['proper_filename'] = $filename;
}
}
// JSON için kontrol
if ( 'json' === $ext ) {
$dosya_icerigi = file_get_contents( $file );
json_decode( $dosya_icerigi );
if ( JSON_ERROR_NONE === json_last_error() ) {
$data['ext'] = 'json';
$data['type'] = 'application/json';
}
}
return $data;
}
add_filter( 'wp_check_filetype_and_ext', 'gelismis_dosya_turu_dogrulama', 10, 4 );
SVG Yükleme: Özel Durum ve Güvenlik
SVG dosyaları WordPress’te özel bir yere sahip çünkü içlerinde JavaScript kodu bulunabilir ve bu ciddi XSS açıklarına yol açar. Sadece izin eklemek yetmez, temizleme de yapmalısınız.
// functions.php - Güvenli SVG yükleme: temizleme ile birlikte
function guvenli_svg_yukleme( $mimes ) {
// Sadece adminler SVG yükleyebilsin
if ( current_user_can( 'administrator' ) ) {
$mimes['svg'] = 'image/svg+xml';
$mimes['svgz'] = 'image/svg+xml';
}
return $mimes;
}
add_filter( 'upload_mimes', 'guvenli_svg_yukleme' );
// SVG dosyasını sanitize et (zararlı script taglerini temizle)
function svg_dosyasini_temizle( $file ) {
if ( isset( $file['type'] ) && 'image/svg+xml' === $file['type'] ) {
$svg_icerigi = file_get_contents( $file['tmp_name'] );
// Script taglerini kaldır
$svg_icerigi = preg_replace( '/<script[sS]*?</script>/i', '', $svg_icerigi );
// on* event handlerlarını kaldır (onclick, onload vb.)
$svg_icerigi = preg_replace( '/s+onw+s*=s*"[^"]*"/i', '', $svg_icerigi );
$svg_icerigi = preg_replace( "/s+onw+s*=s*'[^']*'/i", '', $svg_icerigi );
// javascript: protokolünü kaldır
$svg_icerigi = preg_replace( '/javascript:/i', '', $svg_icerigi );
// Temizlenmiş içeriği geri yaz
file_put_contents( $file['tmp_name'], $svg_icerigi );
}
return $file;
}
add_filter( 'wp_handle_upload_prefilter', 'svg_dosyasini_temizle' );
Uyarı: Yukarıdaki SVG temizleme kodu temel bir örnektir. Üretim ortamı için enshrined/svg-sanitize gibi özel bir PHP kütüphanesi kullanmanızı öneririm.
Dosya Boyutu Kısıtlaması ile Kombinlemek
Dosya türü izinlerini dosya boyutu sınırlamasıyla kombinlemek çok daha güçlü bir güvenlik politikası oluşturur. Özellikle farklı kullanıcı rollerine farklı boyut limitleri atamak isteyebilirsiniz.
// functions.php - Rol bazlı dosya boyutu limiti
function rol_bazli_dosya_boyutu_limiti( $size ) {
if ( current_user_can( 'administrator' ) ) {
// Admin için limit yok (PHP'nin izin verdiği kadar)
return $size;
}
if ( current_user_can( 'editor' ) ) {
// Editor için maksimum 20MB
return 20 * 1024 * 1024; // 20MB byte cinsinden
}
if ( current_user_can( 'author' ) ) {
// Muharrir için maksimum 10MB
return 10 * 1024 * 1024; // 10MB
}
// Diğer tüm roller için maksimum 2MB
return 2 * 1024 * 1024; // 2MB
}
add_filter( 'upload_size_limit', 'rol_bazli_dosya_boyutu_limiti' );
Yükleme Sırasında Özel Doğrulama Eklemek
Bazen sadece dosya türünü değil, dosya içeriğini de kontrol etmek gerekir. Örneğin bir CSV yükleme alanınız var ve bu CSV’nin belirli sütunlara sahip olmasını istiyorsunuz.
// functions.php - Yükleme öncesi özel doğrulama
function ozel_dosya_dogrulama( $file ) {
$dosya_adi = $file['name'];
$uzanti = strtolower( pathinfo( $dosya_adi, PATHINFO_EXTENSION ) );
// CSV dosyaları için özel kontrol
if ( 'csv' === $uzanti ) {
$fp = fopen( $file['tmp_name'], 'r' );
if ( $fp ) {
$ilk_satir = fgetcsv( $fp );
fclose( $fp );
// Beklenen sütunları kontrol et
$beklenen_sutunlar = array( 'ad', 'soyad', 'email', 'telefon' );
$eksik_sutunlar = array_diff( $beklenen_sutunlar, array_map( 'strtolower', $ilk_satir ) );
if ( ! empty( $eksik_sutunlar ) ) {
$file['error'] = sprintf(
'CSV dosyasinda eksik sutunlar var: %s',
implode( ', ', $eksik_sutunlar )
);
}
}
}
// Gorsel dosyaları için boyut kontrolü (minumum 100x100 piksel)
$gorsel_turleri = array( 'jpg', 'jpeg', 'png', 'gif', 'webp' );
if ( in_array( $uzanti, $gorsel_turleri ) ) {
$gorsel_boyutu = getimagesize( $file['tmp_name'] );
if ( $gorsel_boyutu && ( $gorsel_boyutu[0] < 100 || $gorsel_boyutu[1] < 100 ) ) {
$file['error'] = 'Gorsel en az 100x100 piksel olmalidir.';
}
}
return $file;
}
add_filter( 'wp_handle_upload_prefilter', 'ozel_dosya_dogrulama' );
Gerçek Dünya Senaryosu 3: Multisite Kurulumu
WordPress Multisite ortamında çalışıyorsanız MIME kısıtlamaları biraz daha karmaşık hale gelir. Network admin panelinden de ayarlar var ama bunlar her alt site için yeterli olmayabilir.
// functions.php (her alt sitenin child theme'inde) - Multisite için MIME yönetimi
function multisite_mime_yonetimi( $mimes ) {
// Mevcut blog/site ID'sini al
$site_id = get_current_blog_id();
// Site ID'ye göre özel izinler
switch ( $site_id ) {
case 2:
// Tasarım ajansı sitesi: vektör ve tasarım dosyaları
$mimes['svg'] = 'image/svg+xml';
$mimes['ai'] = 'application/postscript';
$mimes['psd'] = 'image/vnd.adobe.photoshop';
$mimes['eps'] = 'application/postscript';
break;
case 3:
// E-ticaret sitesi: sadece güvenli formatlar
$izinli = array(
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'webp' => 'image/webp',
'pdf' => 'application/pdf',
);
return $izinli;
case 4:
// Müzik platformu: ses dosyaları ağırlıklı
$mimes['flac'] = 'audio/flac';
$mimes['aac'] = 'audio/aac';
$mimes['ogg'] = 'audio/ogg';
$mimes['m4a'] = 'audio/mp4';
break;
default:
// Diğer siteler için varsayılan
break;
}
return $mimes;
}
add_filter( 'upload_mimes', 'multisite_mime_yonetimi' );
Hangi MIME Türü Hangi Uzantıya Karşılık Gelir
Kod yazarken doğru MIME türünü bulmak bazen can sıkıcı olabilir. Sık kullanılan bazı kombinasyonlar:
- svg:
image/svg+xml - webp:
image/webp - avif:
image/avif - json:
application/json - xml:
text/xmlveyaapplication/xml - csv:
text/csv - epub:
application/epub+zip - stl:
model/stlveyaapplication/sla - obj:
model/obj - glb:
model/gltf-binary - gltf:
model/gltf+json - woff:
font/woff - woff2:
font/woff2 - ttf:
font/ttf - otf:
font/otf - apk:
application/vnd.android.package-archive - ipa:
application/octet-stream - gz:
application/gzip - tar:
application/x-tar - 7z:
application/x-7z-compressed - rar:
application/x-rar-compressed
Sorun Giderme: Kod Eklediğinizde Hala Hata Varsa
upload_mimes filtresini doğru eklediğiniz halde hata almaya devam ediyorsanız şu kontrolleri yapın:
1. PHP.ini Upload Limiti: upload_max_filesize ve post_max_size değerlerini kontrol edin. WordPress’in kendi limiti değil, PHP’nin limiti de devreye giriyor olabilir.
2. Sunucu Tarafı Kısıtlaması: Apache veya Nginx konfigürasyonunuzda belirli uzantılar engellenmiş olabilir. cPanel kullanan hostinglerde ModSecurity kuralları devreye girmiş olabilir.
3. Güvenlik Plugini: Wordfence, iThemes Security veya benzeri güvenlik pluginleri kendi MIME listelerini uygulayabilir. Plugin ayarlarını kontrol edin.
4. WP_DEBUG ile Test: wp-config.php dosyasına define('WP_DEBUG', true); ekleyip tam hata mesajını görün.
5. Cache Temizleme: Object cache veya opcode cache kullanıyorsanız (Redis, Memcached, OPcache), fonksiyon değişikliklerinin etkili olması için cache’i temizleyin.
Güvenlik Notları
Bu konuda birkaç önemli noktanın altını çizmek istiyorum:
- SVG her zaman risklidir. İçinde JavaScript çalıştırabilir. Sadece güvendiğiniz kullanıcılara izin verin.
- PHP, PHTML, PHAR uzantılarını asla izin listesine eklemeyin. Sunucunuzda kod çalıştırılmasına kapı açar.
- upload_mimes tek başına yetmez. Sunucu tarafında da
.htaccessile PHP’nin belirli dizinlerde çalışmasını engelleyin. - Yükleme dizinini koruyun.
wp-content/uploads/.htaccessdosyasınaphp_flag engine offekleyerek bu dizinde PHP çalışmasını devre dışı bırakın.
Sonuç
WordPress’te dosya türü kısıtlama ve genişletme işlemleri upload_mimes filtresinin temel kullanımıyla başlayıp rol bazlı yönetim, güvenli SVG işleme ve Multisite senaryolarına kadar genişleyebilir. Bu yazıda verilen kod örneklerini ihtiyacınıza göre birleştirerek güçlü bir dosya yükleme politikası oluşturabilirsiniz.
En önemli tavsiye: her şeyi açmak yerine minimum gerekli izni verin. “Bu türe izin vereyim de olsun” mantığı yerine “Bu tür gerçekten gerekli mi?” sorusunu sorun. Özellikle kurumsal ve çok kullanıcılı WordPress kurulumlarında dosya yükleme vektörü sık kullanılan bir saldırı yüzeyi olduğundan, rol bazlı kısıtlamayı mutlaka hayata geçirin. Kod örneklerini child theme’inizin functions.php dosyasına ekleyin ve her değişikliği staging ortamında test ettikten sonra production’a alın.
