From bc0ae5a017bbfc21a4307e823113c1faa4d4d5d3 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 16 Feb 2011 13:46:20 +0100 Subject: [PATCH 01/47] New Indonesian translation (thanks to Irfan Mahfudz Guntur)(EJAB-1407) --- src/msgs/id.msg | 408 +++++++++++ src/msgs/id.po | 1799 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2207 insertions(+) create mode 100644 src/msgs/id.msg create mode 100644 src/msgs/id.po diff --git a/src/msgs/id.msg b/src/msgs/id.msg new file mode 100644 index 000000000..d843e1ed6 --- /dev/null +++ b/src/msgs/id.msg @@ -0,0 +1,408 @@ +{"Access Configuration","Akses Konfigurasi"}. +{"Access Control List Configuration","Konfigurasi Daftar Akses Pengendalian"}. +{"Access Control Lists","Akses Daftar Pengendalian"}. +{"Access control lists","Daftar Pengendalian Akses"}. +{"Access denied by service policy","Akses ditolak oleh kebijakan layanan"}. +{"Access rules","Akses peraturan"}. +{"Access Rules","Aturan Akses"}. +{"Action on user","Tindakan pada pengguna"}. +{"Add Jabber ID","Tambah Jabber ID"}. +{"Add New","Tambah Baru"}. +{"Add User","Tambah Pengguna"}. +{"Administration","Administrasi"}. +{"Administration of ","Administrasi"}. +{"Administrator privileges required","Hak istimewa Administrator dibutuhkan"}. +{"A friendly name for the node","Nama yang dikenal untuk node"}. +{"All activity","Semua aktifitas"}. +{"Allow this Jabber ID to subscribe to this pubsub node?","Izinkan ID Jabber ini untuk berlangganan pada node pubsub ini?"}. +{"Allow users to change the subject","Perbolehkan pengguna untuk mengganti topik"}. +{"Allow users to query other users","Perbolehkan pengguna untuk mengetahui pengguna lain"}. +{"Allow users to send invites","Perbolehkan pengguna mengirimkan undangan"}. +{"Allow users to send private messages","perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi"}. +{"Allow visitors to change nickname","Perbolehkan visitor mengganti nama julukan"}. +{"Allow visitors to send status text in presence updates","Izinkan pengunjung untuk mengirim teks status terbaru"}. +{"All Users","Semua Pengguna"}. +{"Announcements","Pengumuman"}. +{"anyone","Siapapun"}. +{"A password is required to enter this room","Diperlukan kata sandi untuk masuk ruangan ini"}. +{"April","April"}. +{"August","Agustus"}. +{"Backup","Backup"}. +{"Backup Management","Manajemen Backup"}. +{"Backup of ","Cadangan dari"}. +{"Backup to File at ","Backup ke File pada"}. +{"Bad format","Format yang buruk"}. +{"Birthday","Hari Lahir"}. +{"CAPTCHA web page","CAPTCHA laman web"}. +{"Change Password","Ubah Kata Sandi"}. +{"Change User Password","Ubah User Password"}. +{"Characters not allowed:","Karakter tidak diperbolehkan:"}. +{"Chatroom configuration modified","Konfigurasi ruang chat diubah"}. +{"Chatroom is created","Ruang chat telah dibuat"}. +{"Chatroom is destroyed","Ruang chat dilenyapkan"}. +{"Chatroom is started","Ruang chat dimulai"}. +{"Chatroom is stopped","Ruang chat dihentikan"}. +{"Chatrooms","Ruangan Chat"}. +{"Choose a username and password to register with this server","Pilih nama pengguna dan kata sandi untuk mendaftar dengan layanan ini"}. +{"Choose modules to stop","Pilih Modul untuk berhenti"}. +{"Choose storage type of tables","Pilih jenis penyimpanan tabel"}. +{"Choose whether to approve this entity's subscription.","Pilih apakah akan menyetujui hubungan pertemanan ini."}. +{"City","Kota"}. +{"Commands","Perintah"}. +{"Conference room does not exist","Ruang Konferensi tidak ada"}. +{"Configuration of room ~s","Pengaturan ruangan ~s"}. +{"Configuration","Pengaturan"}. +{"Connected Resources:","Sumber Daya Terhubung:"}. +{"Connections parameters","Parameter Koneksi"}. +{"Country","Negara"}. +{"CPU Time:","Waktu CPU:"}. +{"Database","Database"}. +{"Database Tables at ","Tabel Database pada"}. +{"Database Tables Configuration at ","Database Tabel Konfigurasi pada"}. +{"December","Desember"}. +{"Default users as participants","pengguna pertama kali masuk sebagai participant"}. +{"Delete","Hapus"}. +{"Delete message of the day","Hapus pesan harian"}. +{"Delete message of the day on all hosts","Hapus pesan harian pada semua host"}. +{"Delete Selected","Hapus Yang Terpilih"}. +{"Delete User","Hapus Pengguna"}. +{"Deliver event notifications","Memberikan pemberitahuan acara"}. +{"Deliver payloads with event notifications","Memberikan muatan dengan pemberitahuan acara"}. +{"Description:","Keterangan:"}. +{"Disc only copy","Hanya salinan dari disc"}. +{"Displayed Groups:","Tampilkan Grup:"}. +{"Don't tell your password to anybody, not even the administrators of the Jabber server.","Jangan memberitahukan kata sandi Anda ke siapapun, bahkan para administrator dari layanan Jabber."}. +{"Dump Backup to Text File at ","Dump Backup ke File Teks di"}. +{"Dump to Text File","Dump menjadi File Teks"}. +{"Edit Properties","Ganti Properti"}. +{"ejabberd IRC module","ejabberd IRC modul"}. +{"ejabberd MUC module","ejabberd MUC Module"}. +{"ejabberd Publish-Subscribe module","Modul ejabberd Setujui-Pertemanan"}. +{"ejabberd SOCKS5 Bytestreams module","modul ejabberd SOCKS5 Bytestreams"}. +{"ejabberd vCard module","Modul ejabberd vCard"}. +{"ejabberd virtual hosts","ejabberd virtual hosts"}. +{"ejabberd Web Admin","Admin Web ejabberd"}. +{"Elements","Elemen-elemen"}. +{"Email","Email"}. +{"Enable logging","Aktifkan catatan"}. +{"Encoding for server ~b","Pengkodean untuk layanan ~b"}. +{"End User Session","Akhir Sesi Pengguna"}. +{"Enter list of {Module, [Options]}","Masukkan daftar {Modul, [Options]}"}. +{"Enter nickname you want to register","Masukkan nama julukan Anda jika ingin mendaftar"}. +{"Enter path to backup file","Masukkan path untuk file cadangan"}. +{"Enter path to jabberd14 spool dir","Masukkan path ke direktori spool jabberd14"}. +{"Enter path to jabberd14 spool file","Masukkan path ke file jabberd14 spool"}. +{"Enter path to text file","Masukkan path ke file teks"}. +{"Enter the text you see","Masukkan teks yang Anda lihat"}. +{"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","Masukkan username dan pengkodean yang ingin Anda gunakan untuk menghubungkan ke layanan IRC. Tekan 'Selanjutnya' untuk mendapatkan lagi formulir kemudian Tekan 'Lengkap' untuk menyimpan pengaturan."}. +{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Masukkan username, pengkodean, port dan sandi yang ingin Anda gunakan untuk menghubungkan ke layanan IRC"}. +{"Erlang Jabber Server","Layanan Erlang Jabber"}. +{"Error","Kesalahan"}. +{"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Contoh: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. +{"Export data of all users in the server to PIEFXIS files (XEP-0227):","Ekspor data dari semua pengguna pada layanan ke berkas PIEFXIS (XEP-0227):"}. +{"Export data of users in a host to PIEFXIS files (XEP-0227):","Ekspor data pengguna pada sebuah host ke berkas PIEFXIS (XEP-0227):"}. +{"Family Name","Nama Keluarga (marga)"}. +{"February","Februari"}. +{"Fill in fields to search for any matching Jabber User","Isi kolom untuk mencari pengguna Jabber yang sama"}. +{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Isi formulir untuk pencarian pengguna Jabber yang cocok (Tambahkan * ke mengakhiri pengisian untuk menyamakan kata)"}. +{"Friday","Jumat"}. +{"From","Dari"}. +{"From ~s","Dari ~s"}. +{"Full Name","Nama Lengkap"}. +{"Get Number of Online Users","Dapatkan Jumlah User Yang Online"}. +{"Get Number of Registered Users","Dapatkan Jumlah Pengguna Yang Terdaftar"}. +{"Get User Last Login Time","Dapatkan Waktu Login Terakhir Pengguna "}. +{"Get User Password","Dapatkan User Password"}. +{"Get User Statistics","Dapatkan Statistik Pengguna"}. +{"Group ","Grup"}. +{"Groups","Grup"}. +{"has been banned","telah dibanned"}. +{"has been kicked because of an affiliation change","telah dikick karena perubahan afiliasi"}. +{"has been kicked because of a system shutdown","telah dikick karena sistem shutdown"}. +{"has been kicked because the room has been changed to members-only","telah dikick karena ruangan telah diubah menjadi hanya untuk member"}. +{"has been kicked","telah dikick"}. +{" has set the subject to: ","telah menetapkan topik yaitu:"}. +{"Host","Host"}. +{"If you don't see the CAPTCHA image here, visit the web page.","Jika Anda tidak melihat gambar CAPTCHA disini, silahkan kunjungi halaman web."}. +{"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","Jika Anda ingin menentukan port yang berbeda, sandi, pengkodean untuk layanan IRC, isi daftar ini dengan nilai-nilai dalam format '{\"server irc \", \"encoding \", port, \"sandi \"}'. Secara default ini menggunakan layanan \"~s \" pengkodean, port ~p, kata sandi kosong."}. +{"Import Directory","Impor Direktori"}. +{"Import File","Impor File"}. +{"Import user data from jabberd14 spool file:","Impor data pengguna dari sekumpulan berkas jabberd14:"}. +{"Import User from File at ","Impor Pengguna dari File pada"}. +{"Import users data from a PIEFXIS file (XEP-0227):","impor data-data pengguna dari sebuah PIEFXIS (XEP-0227):"}. +{"Import users data from jabberd14 spool directory:","Импорт пользовательских данных из буферной директории jabberd14:"}. +{"Import Users from Dir at ","Impor Pengguna dari Dir di"}. +{"Import Users From jabberd14 Spool Files","Impor Pengguna Dari jabberd14 Spool File"}. +{"Improper message type","Jenis pesan yang tidak benar"}. +{"Incorrect password","Kata sandi salah"}. +{"Invalid affiliation: ~s","Afiliasi tidak valid: ~s"}. +{"Invalid role: ~s","Peran tidak valid: ~s"}. +{"IP addresses","Alamat IP"}. +{"IP","IP"}. +{"IRC channel (don't put the first #)","Channel IRC (tidak perlu menempatkan # sebelumnya)"}. +{"IRC server","Layanan IRC"}. +{"IRC settings","Pengaturan IRC"}. +{"IRC Transport","IRC Transport"}. +{"IRC username","Nama Pengguna IRC"}. +{"IRC Username","Nama Pengguna IRC"}. +{"is now known as","sekarang dikenal sebagai"}. +{"It is not allowed to send private messages","Hal ini tidak diperbolehkan untuk mengirim pesan pribadi"}. +{"It is not allowed to send private messages of type \"groupchat\"","Hal ini tidak diperbolehkan untuk mengirim pesan pribadi jenis \"groupchat \""}. +{"It is not allowed to send private messages to the conference","Hal ini tidak diperbolehkan untuk mengirim pesan pribadi ke konferensi"}. +{"Jabber Account Registration","Pendaftaran Akun Jabber"}. +{"Jabber ID","Jabber ID"}. +{"Jabber ID ~s is invalid","Jabber ID ~s tidak valid"}. +{"January","Januari"}. +{"Join IRC channel","Gabung channel IRC"}. +{"joins the room","bergabung ke ruangan"}. +{"Join the IRC channel here.","Gabung ke channel IRC disini"}. +{"Join the IRC channel in this Jabber ID: ~s","Gabung ke channel IRC dengan Jabber ID: ~s"}. +{"July","Juli"}. +{"June","Juni"}. +{"Last Activity","Aktifitas Terakhir"}. +{"Last login","Terakhir Login"}. +{"Last month","Akhir bulan"}. +{"Last year","Akhir tahun"}. +{"leaves the room","meninggalkan ruangan"}. +{"Listened Ports at ","Mendeteksi Port-port di"}. +{"Listened Ports","Port Terdeteksi"}. +{"List of modules to start","Daftar modul untuk memulai"}. +{"Low level update script","Perbaruan naskah tingkat rendah"}. +{"Make participants list public","Buat daftar participant diketahui oleh public"}. +{"Make room captcha protected","Buat ruangan dilindungi dengan chapta"}. +{"Make room members-only","Buat ruangan hanya untuk member saja"}. +{"Make room moderated","Buat ruangan hanya untuk moderator saja"}. +{"Make room password protected","Buat ruangan yang dilindungi dengan kata sandi"}. +{"Make room persistent","Buat ruangan menjadi permanent"}. +{"Make room public searchable","Buat ruangan dapat dicari"}. +{"March","Maret"}. +{"Maximum Number of Occupants","Maksimum Jumlah Penghuni"}. +{"Max # of items to persist","Max item untuk bertahan"}. +{"Max payload size in bytes","Max kapasitas ukuran dalam bytes"}. +{"May","Mei"}. +{"Members:","Anggota:"}. +{"Membership is required to enter this room","Hanya Member yang dapat masuk ruangan ini"}. +{"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Hafalkan kata sandi Anda, atau dicatat dan letakkan di tempat yang aman. Didalam Jabber tidak ada cara otomatis untuk mendapatkan kembali password Anda jika Anda lupa."}. +{"Memory","Memori"}. +{"Message body","Isi Pesan"}. +{"Middle Name","Nama Tengah"}. +{"Moderator privileges required","Hak istimewa moderator dibutuhkan"}. +{"moderators only","Hanya moderator"}. +{"Modified modules","Modifikasi modul-modul"}. +{"Module","Modul"}. +{"Modules at ","modul-modul di"}. +{"Modules","Modul"}. +{"Monday","Senin"}. +{"Name:","Nama:"}. +{"Name","Nama"}. +{"Never","Tidak Pernah"}. +{"New Password:","Password Baru:"}. +{"Nickname","Nama Julukan"}. +{"Nickname Registration at ","Pendaftaran Julukan pada"}. +{"Nickname ~s does not exist in the room","Nama Julukan ~s tidak berada di dalam ruangan"}. +{"No body provided for announce message","Tidak ada isi pesan yang disediakan untuk mengirimkan pesan"}. +{"No Data","Tidak Ada Data"}. +{"Node ID","ID Node"}. +{"Node ","Node"}. +{"Node not found","Node tidak ditemukan"}. +{"Nodes","Node-node"}. +{"No limit","Tidak terbatas"}. +{"None","Tak satupun"}. +{"No resource provided","Tidak ada sumber daya yang disediakan"}. +{"Not Found","Tidak Ditemukan"}. +{"Notify subscribers when items are removed from the node","Beritahu pelanggan ketika item tersebut dikeluarkan dari node"}. +{"Notify subscribers when the node configuration changes","Beritahu pelanggan ketika ada perubahan konfigurasi node"}. +{"Notify subscribers when the node is deleted","Beritahu pelanggan ketika node dihapus"}. +{"November","Nopember"}. +{"Number of occupants","Jumlah Penghuni"}. +{"Number of online users","Jumlah pengguna online"}. +{"Number of registered users","Jumlah pengguna terdaftar"}. +{"October","Oktober"}. +{"Offline Messages:","Pesan Offline:"}. +{"Offline Messages","Pesan Offline"}. +{"OK","YA"}. +{"Old Password:","Password Lama:"}. +{"Online","Online"}. +{"Online Users:","Pengguna Online:"}. +{"Online Users","Pengguna Yang Online"}. +{"Only deliver notifications to available users","Hanya mengirimkan pemberitahuan kepada pengguna yang tersedia"}. +{"Only moderators and participants are allowed to change the subject in this room","Hanya moderator dan peserta yang diizinkan untuk mengganti topik pembicaraan di ruangan ini"}. +{"Only moderators are allowed to change the subject in this room","Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini"}. +{"Only occupants are allowed to send messages to the conference","Hanya penghuni yang diizinkan untuk mengirim pesan ke konferensi"}. +{"Only occupants are allowed to send queries to the conference","Hanya penghuni diizinkan untuk mengirim permintaan ke konferensi"}. +{"Only service administrators are allowed to send service messages","Layanan hanya diperuntukan kepada administrator yang diizinkan untuk mengirim layanan pesan"}. +{"Options","Pilihan-pilihan"}. +{"Organization Name","Nama Organisasi"}. +{"Organization Unit","Unit Organisasi"}. +{"Outgoing s2s Connections","Koneksi Keluar s2s"}. +{"Outgoing s2s Connections:","Koneksi s2s yang keluar:"}. +{"Outgoing s2s Servers:","Layanan s2s yang keluar:"}. +{"Owner privileges required","Hak istimewa owner dibutuhkan"}. +{"Packet","Paket"}. +{"Password ~b","Kata Sandi ~b"}. +{"Password:","Kata Sandi:"}. +{"Password","Sandi"}. +{"Password Verification:","Verifikasi Kata Sandi:"}. +{"Password Verification","Verifikasi Sandi"}. +{"Path to Dir","Jalur ke Dir"}. +{"Path to File","Jalur ke File"}. +{"Pending","Tertunda"}. +{"Period: ","Periode:"}. +{"Persist items to storage","Pertahankan item ke penyimpanan"}. +{"Ping","Ping"}. +{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Harap dicatat bahwa pilihan ini hanya akan membuat cadangan builtin Mnesia database. Jika Anda menggunakan modul ODBC, anda juga perlu untuk membuat cadangan database SQL Anda secara terpisah."}. +{"Pong","Pong"}. +{"Port ~b","Port ~b"}. +{"Port","Port"}. +{"Present real Jabber IDs to","Tampilkan Jabber ID secara lengkap"}. +{"private, ","pribadi, "}. +{"Protocol","Protocol"}. +{"Publish-Subscribe","Setujui-Pertemanan"}. +{"PubSub subscriber request","Permintaan pertemanan PubSub"}. +{"Purge all items when the relevant publisher goes offline","Bersihkan semua item ketika penerbit yang relevan telah offline"}. +{"Queries to the conference members are not allowed in this room","Permintaan untuk para anggota konferensi tidak diperbolehkan di ruangan ini"}. +{"RAM and disc copy","RAM dan disc salinan"}. +{"RAM copy","Salinan RAM"}. +{"Raw","mentah"}. +{"Really delete message of the day?","Benar-benar ingin menghapus pesan harian?"}. +{"Recipient is not in the conference room","Penerima tidak berada di ruangan konferensi"}. +{"Register a Jabber account","Daftarkan sebuah akun jabber"}. +{"Registered Users:","Pengguna Terdaftar:"}. +{"Registered Users","Pengguna Terdaftar"}. +{"Register","Mendaftar"}. +{"Registration in mod_irc for ","Pendaftaran di mod_irc untuk"}. +{"Remote copy","Salinan Remote"}. +{"Remove All Offline Messages","Hapus Semua Pesan Offline"}. +{"Remove","Menghapus"}. +{"Remove User","Hapus Pengguna"}. +{"Replaced by new connection","Diganti dengan koneksi baru"}. +{"Resources","Sumber daya"}. +{"Restart","Jalankan Ulang"}. +{"Restart Service","Restart Layanan"}. +{"Restore Backup from File at ","Kembalikan Backup dari File pada"}. +{"Restore binary backup after next ejabberd restart (requires less memory):","Mengembalikan cadangan yang berpasanagn setelah ejabberd berikutnya dijalankan ulang (memerlukan memori lebih sedikit):"}. +{"Restore binary backup immediately:","Segera mengembalikan cadangan yang berpasangan:"}. +{"Restore","Mengembalikan"}. +{"Restore plain text backup immediately:","Segera mengembalikan cadangan teks biasa:"}. +{"Room Configuration","Konfigurasi Ruangan"}. +{"Room creation is denied by service policy","Pembuatan Ruangan ditolak oleh kebijakan layanan"}. +{"Room description","Keterangan ruangan"}. +{"Room Occupants","Penghuni Ruangan"}. +{"Room title","Nama Ruangan"}. +{"Roster groups allowed to subscribe","Kelompok kontak yang diizinkan untuk berlangganan"}. +{"Roster","Kontak"}. +{"Roster of ","Kontak dari"}. +{"Roster size","Ukuran Daftar Kontak"}. +{"RPC Call Error","Panggilan Kesalahan RPC"}. +{"Running Nodes","Menjalankan Node"}. +{"~s access rule configuration","~s aturan akses konfigurasi"}. +{"Saturday","Sabtu"}. +{"Script check","Periksa naskah"}. +{"Search Results for ","Hasil Pencarian untuk"}. +{"Search users in ","Pencarian pengguna dalam"}. +{"Send announcement to all online users","Kirim pengumuman untuk semua pengguna yang online"}. +{"Send announcement to all online users on all hosts","Kirim pengumuman untuk semua pengguna yang online pada semua host"}. +{"Send announcement to all users","Kirim pengumuman untuk semua pengguna"}. +{"Send announcement to all users on all hosts","Kirim pengumuman untuk semua pengguna pada semua host"}. +{"September","September"}. +{"Server ~b","Layanan ~b"}. +{"Server:","Layanan:"}. +{"Set message of the day and send to online users","Mengatur pesan harian dan mengirimkan ke pengguna yang online"}. +{"Set message of the day on all hosts and send to online users","Mengatur pesan harian pada semua host dan kirimkan ke pengguna yang online"}. +{"Shared Roster Groups","Berbagi grup kontak"}. +{"Show Integral Table","Tampilkan Tabel Terpisah"}. +{"Show Ordinary Table","Tampilkan Tabel Normal"}. +{"Shut Down Service","Shut Down Layanan"}. +{"~s invites you to the room ~s","~s mengundang anda ke ruangan ~s"}. +{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Beberapa klien Jabber dapat menyimpan password di komputer Anda. Gunakan fitur itu hanya jika Anda mempercayai komputer Anda aman."}. +{"Specify the access model","Tentukan model akses"}. +{"Specify the event message type","Tentukan jenis acara pesan"}. +{"Specify the publisher model","Tentukan model penerbitan"}. +{"~s's Offline Messages Queue","Antrian Pesan Offline ~s"}. +{"Start Modules at ","Mulai Modul pada"}. +{"Start Modules","Memulai Modul"}. +{"Start","Mulai"}. +{"Statistics of ~p","statistik dari ~p"}. +{"Statistics","Statistik"}. +{"Stop","Hentikan"}. +{"Stop Modules at ","Hentikan Modul pada"}. +{"Stop Modules","Hentikan Modul"}. +{"Stopped Nodes","Menghentikan node"}. +{"Storage Type","Jenis Penyimpanan"}. +{"Store binary backup:","Penyimpanan cadangan yang berpasangan:"}. +{"Store plain text backup:","Simpan cadangan teks biasa:"}. +{"Subject","Subyek"}. +{"Submit","Serahkan"}. +{"Submitted","Ulangi masukan"}. +{"Subscriber Address","Alamat Pertemanan"}. +{"Subscription","Berlangganan"}. +{"Sunday","Minggu"}. +{"That nickname is already in use by another occupant","Julukan itu sudah digunakan oleh penghuni lain"}. +{"That nickname is registered by another person","Julukan tersebut telah didaftarkan oleh orang lain"}. +{"The captcha is valid.","Captcha ini benar."}. +{"The CAPTCHA verification has failed","Verifikasi CAPTCHA telah gagal"}. +{"The collections with which a node is affiliated","Koleksi dengan yang berafiliasi dengan sebuah node"}. +{"the password is","kata sandi yaitu:"}. +{"The password is too weak","Kata sandi terlalu lemah"}. +{"The password of your Jabber account was successfully changed.","Kata sandi pada akun Jabber Anda telah berhasil diubah."}. +{"There was an error changing the password: ","Ada kesalahan dalam mengubah password:"}. +{"There was an error creating the account: ","Ada kesalahan saat membuat akun:"}. +{"There was an error deleting the account: ","Ada kesalahan saat menghapus akun:"}. +{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Pada bagian ini huruf besar dan kecil tidak dibedakan: Misalnya macbeth adalah sama dengan MacBeth juga Macbeth."}. +{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Halaman ini memungkinkan untuk membuat akun Jabber di layanan Jabber ini. JID Anda (Jabber Pengenal) akan berbentuk: namapengguna@layanan. Harap baca dengan seksama petunjuk-petunjuk untuk mengisi kolom dengan benar."}. +{"This page allows to unregister a Jabber account in this Jabber server.","Pada bagian ini memungkinkan Anda untuk membatalkan pendaftaran akun Jabber pada layanan Jabber ini."}. +{"This participant is kicked from the room because he sent an error message","Peserta ini dikick dari ruangan karena dia mengirim pesan kesalahan"}. +{"This participant is kicked from the room because he sent an error message to another participant","Participant ini dikick dari ruangan karena ia mengirim pesan kesalahan ke participant lain"}. +{"This participant is kicked from the room because he sent an error presence","Participant ini dikick dari ruangan karena ia mengirim kehadiran kesalahan"}. +{"This room is not anonymous","Ruangan ini tidak dikenal"}. +{"Thursday","Kamis"}. +{"Time delay","Waktu tunda"}. +{"Time","Waktu"}. +{"To","Kepada"}. +{"To ~s","Kepada ~s"}. +{"Traffic rate limit is exceeded","Lalu lintas melebihi batas"}. +{"Transactions Aborted:","Transaksi yang dibatalkan:"}. +{"Transactions Committed:","Transaksi yang dilakukan:"}. +{"Transactions Logged:","Transaksi yang ditempuh:"}. +{"Transactions Restarted:","Transaksi yang dijalankan ulang:"}. +{"Tuesday","Selasa"}. +{"Unable to generate a captcha","Tidak dapat menghasilkan captcha"}. +{"Unable to generate a CAPTCHA","Tidak dapat menghasilkan CAPTCHA"}. +{"Unauthorized","Ditolak"}. +{"Unregister a Jabber account","Nonaktifkan akun jabber"}. +{"Unregister","Nonaktifkan"}. +{"Update ","Memperbarui "}. +{"Update","Memperbarui"}. +{"Update message of the day (don't send)","Rubah pesan harian (tidak dikirim)"}. +{"Update message of the day on all hosts (don't send)","Rubah pesan harian pada semua host (tidak dikirim)"}. +{"Update plan","Rencana Perubahan"}. +{"Update script","Perbarui naskah"}. +{"Uptime:","Sampai saat:"}. +{"Use of STARTTLS required","Penggunaan STARTTLS diperlukan"}. +{"User Management","Manajemen Pengguna"}. +{"Username:","Nama Pengguna:"}. +{"User ","Pengguna"}. +{"User","Pengguna"}. +{"Users are not allowed to register accounts so quickly","Pengguna tidak diperkenankan untuk mendaftar akun begitu cepat"}. +{"Users Last Activity","Aktifitas terakhir para pengguna"}. +{"Users","Pengguna"}. +{"Validate","Mengesahkan"}. +{"vCard User Search","vCard Pencarian Pengguna"}. +{"Visitors are not allowed to change their nicknames in this room","Visitor tidak diperbolehkan untuk mengubah nama julukan di ruangan ini"}. +{"Visitors are not allowed to send messages to all occupants","Visitor tidak diperbolehkan untuk mengirim pesan ke semua penghuni"}. +{"Wednesday","Rabu"}. +{"When to send the last published item","Ketika untuk mengirim item terakhir yang dipublikasikan"}. +{"Whether to allow subscriptions","Apakah diperbolehkan untuk berlangganan"}. +{"You can later change your password using a Jabber client.","Anda dapat mengubah kata sandi anda dilain waktu dengan menggunakan klien Jabber."}. +{"You have been banned from this room","Anda telah diblokir dari ruangan ini"}. +{"You must fill in field \"Nickname\" in the form","Anda harus mengisi kolom \"Julukan\" dalam formulir"}. +{"You need a client that supports x:data and CAPTCHA to register","Anda memerlukan klien yang mendukung x:data dan CAPTCHA untuk mendaftar"}. +{"You need a client that supports x:data to register the nickname","Anda memerlukan klien yang mendukung x:data untuk mendaftar julukan"}. +{"You need an x:data capable client to configure mod_irc settings","Anda memerlukan x:data klien untuk mampu mengkonfigurasi pengaturan mod_irc"}. +{"You need an x:data capable client to configure room","Anda memerlukan x:data klien untuk dapat mengkonfigurasi ruangan"}. +{"You need an x:data capable client to search","Anda memerlukan x:data klien untuk melakukan pencarian"}. +{"Your active privacy list has denied the routing of this stanza.","Daftar privasi aktif Anda telah menolak routing ztanza ini"}. +{"Your contact offline message queue is full. The message has been discarded.","Kontak offline Anda pada antrian pesan sudah penuh. Pesan telah dibuang."}. +{"Your Jabber account was successfully created.","Jabber akun Anda telah sukses dibuat"}. +{"Your Jabber account was successfully deleted.","Jabber akun Anda berhasil dihapus."}. +{"Your messages to ~s are being blocked. To unblock them, visit ~s","Pesan Anda untuk ~s sedang diblokir. Untuk membuka blokir tersebut, kunjungi ~s"}. diff --git a/src/msgs/id.po b/src/msgs/id.po new file mode 100644 index 000000000..4dca85ad1 --- /dev/null +++ b/src/msgs/id.po @@ -0,0 +1,1799 @@ +# , 2010. +msgid "" +msgstr "" +"Project-Id-Version: 2.1.0-alpha\n" +"PO-Revision-Date: 2011-02-15 07:09+0800\n" +"Last-Translator: Irfan Mahfudz Guntur \n" +"Language-Team: SmartCommunity \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: Indonesian (Bahasa Indonesia)\n" + +#: ejabberd_c2s.erl:424 ejabberd_c2s.erl:727 +msgid "Use of STARTTLS required" +msgstr "Penggunaan STARTTLS diperlukan" + +#: ejabberd_c2s.erl:503 +msgid "No resource provided" +msgstr "Tidak ada sumber daya yang disediakan" + +#: ejabberd_c2s.erl:1147 +msgid "Replaced by new connection" +msgstr "Diganti dengan koneksi baru" + +#: ejabberd_c2s.erl:1832 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Daftar privasi aktif Anda telah menolak routing ztanza ini" + +#: ejabberd_captcha.erl:94 ejabberd_captcha.erl:150 ejabberd_captcha.erl:176 +msgid "Enter the text you see" +msgstr "Masukkan teks yang Anda lihat" + +#: ejabberd_captcha.erl:99 +msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" +msgstr "" +"Pesan Anda untuk ~s sedang diblokir. Untuk membuka blokir tersebut, kunjungi " +"~s" + +#: ejabberd_captcha.erl:132 +msgid "If you don't see the CAPTCHA image here, visit the web page." +msgstr "" +"Jika Anda tidak melihat gambar CAPTCHA disini, silahkan kunjungi halaman web." + +#: ejabberd_captcha.erl:144 +msgid "CAPTCHA web page" +msgstr "CAPTCHA laman web" + +#: ejabberd_captcha.erl:302 +msgid "The captcha is valid." +msgstr "Captcha ini benar." + +#: mod_adhoc.erl:95 mod_adhoc.erl:125 mod_adhoc.erl:143 mod_adhoc.erl:161 +msgid "Commands" +msgstr "Perintah" + +#: mod_adhoc.erl:149 mod_adhoc.erl:243 +msgid "Ping" +msgstr "Ping" + +#: mod_adhoc.erl:260 +msgid "Pong" +msgstr "Pong" + +#: mod_announce.erl:506 +msgid "Really delete message of the day?" +msgstr "Benar-benar ingin menghapus pesan harian?" + +#: mod_announce.erl:514 mod_configure.erl:1083 mod_configure.erl:1128 +msgid "Subject" +msgstr "Subyek" + +#: mod_announce.erl:519 mod_configure.erl:1088 mod_configure.erl:1133 +msgid "Message body" +msgstr "Isi Pesan" + +#: mod_announce.erl:599 +msgid "No body provided for announce message" +msgstr "Tidak ada isi pesan yang disediakan untuk mengirimkan pesan" + +#: mod_announce.erl:634 +msgid "Announcements" +msgstr "Pengumuman" + +#: mod_announce.erl:636 +msgid "Send announcement to all users" +msgstr "Kirim pengumuman untuk semua pengguna" + +#: mod_announce.erl:638 +msgid "Send announcement to all users on all hosts" +msgstr "Kirim pengumuman untuk semua pengguna pada semua host" + +#: mod_announce.erl:640 +msgid "Send announcement to all online users" +msgstr "Kirim pengumuman untuk semua pengguna yang online" + +#: mod_announce.erl:642 mod_configure.erl:1078 mod_configure.erl:1123 +msgid "Send announcement to all online users on all hosts" +msgstr "Kirim pengumuman untuk semua pengguna yang online pada semua host" + +#: mod_announce.erl:644 +msgid "Set message of the day and send to online users" +msgstr "Mengatur pesan harian dan mengirimkan ke pengguna yang online" + +#: mod_announce.erl:646 +msgid "Set message of the day on all hosts and send to online users" +msgstr "" +"Mengatur pesan harian pada semua host dan kirimkan ke pengguna yang online" + +#: mod_announce.erl:648 +msgid "Update message of the day (don't send)" +msgstr "Rubah pesan harian (tidak dikirim)" + +#: mod_announce.erl:650 +msgid "Update message of the day on all hosts (don't send)" +msgstr "Rubah pesan harian pada semua host (tidak dikirim)" + +#: mod_announce.erl:652 +msgid "Delete message of the day" +msgstr "Hapus pesan harian" + +#: mod_announce.erl:654 +msgid "Delete message of the day on all hosts" +msgstr "Hapus pesan harian pada semua host" + +#: mod_configure.erl:114 mod_configure.erl:274 mod_configure.erl:296 +#: mod_configure.erl:498 +msgid "Configuration" +msgstr "Pengaturan" + +#: mod_configure.erl:125 mod_configure.erl:576 web/ejabberd_web_admin.erl:1930 +msgid "Database" +msgstr "Database" + +#: mod_configure.erl:127 mod_configure.erl:595 +msgid "Start Modules" +msgstr "Memulai Modul" + +#: mod_configure.erl:129 mod_configure.erl:596 +msgid "Stop Modules" +msgstr "Hentikan Modul" + +#: mod_configure.erl:131 mod_configure.erl:604 web/ejabberd_web_admin.erl:1931 +msgid "Backup" +msgstr "Backup" + +#: mod_configure.erl:133 mod_configure.erl:605 +msgid "Restore" +msgstr "Mengembalikan" + +#: mod_configure.erl:135 mod_configure.erl:606 +msgid "Dump to Text File" +msgstr "Dump menjadi File Teks" + +#: mod_configure.erl:137 mod_configure.erl:615 +msgid "Import File" +msgstr "Impor File" + +#: mod_configure.erl:139 mod_configure.erl:616 +msgid "Import Directory" +msgstr "Impor Direktori" + +#: mod_configure.erl:141 mod_configure.erl:581 mod_configure.erl:1057 +msgid "Restart Service" +msgstr "Restart Layanan" + +#: mod_configure.erl:143 mod_configure.erl:582 mod_configure.erl:1102 +msgid "Shut Down Service" +msgstr "Shut Down Layanan" + +#: mod_configure.erl:145 mod_configure.erl:518 mod_configure.erl:1197 +#: web/ejabberd_web_admin.erl:1524 +msgid "Add User" +msgstr "Tambah Pengguna" + +#: mod_configure.erl:147 mod_configure.erl:519 mod_configure.erl:1219 +msgid "Delete User" +msgstr "Hapus Pengguna" + +#: mod_configure.erl:149 mod_configure.erl:520 mod_configure.erl:1231 +msgid "End User Session" +msgstr "Akhir Sesi Pengguna" + +#: mod_configure.erl:151 mod_configure.erl:521 mod_configure.erl:1243 +#: mod_configure.erl:1255 +msgid "Get User Password" +msgstr "Dapatkan User Password" + +#: mod_configure.erl:153 mod_configure.erl:522 +msgid "Change User Password" +msgstr "Ubah User Password" + +#: mod_configure.erl:155 mod_configure.erl:523 mod_configure.erl:1272 +msgid "Get User Last Login Time" +msgstr "Dapatkan Waktu Login Terakhir Pengguna " + +#: mod_configure.erl:157 mod_configure.erl:524 mod_configure.erl:1284 +msgid "Get User Statistics" +msgstr "Dapatkan Statistik Pengguna" + +#: mod_configure.erl:159 mod_configure.erl:525 +msgid "Get Number of Registered Users" +msgstr "Dapatkan Jumlah Pengguna Yang Terdaftar" + +#: mod_configure.erl:161 mod_configure.erl:526 +msgid "Get Number of Online Users" +msgstr "Dapatkan Jumlah User Yang Online" + +#: mod_configure.erl:163 mod_configure.erl:509 web/ejabberd_web_admin.erl:827 +#: web/ejabberd_web_admin.erl:868 +msgid "Access Control Lists" +msgstr "Akses Daftar Pengendalian" + +#: mod_configure.erl:165 mod_configure.erl:510 web/ejabberd_web_admin.erl:936 +#: web/ejabberd_web_admin.erl:972 +msgid "Access Rules" +msgstr "Aturan Akses" + +#: mod_configure.erl:297 mod_configure.erl:499 +msgid "User Management" +msgstr "Manajemen Pengguna" + +#: mod_configure.erl:500 web/ejabberd_web_admin.erl:1054 +#: web/ejabberd_web_admin.erl:1459 +msgid "Online Users" +msgstr "Pengguna Yang Online" + +#: mod_configure.erl:501 +msgid "All Users" +msgstr "Semua Pengguna" + +#: mod_configure.erl:502 +msgid "Outgoing s2s Connections" +msgstr "Koneksi Keluar s2s" + +#: mod_configure.erl:503 web/ejabberd_web_admin.erl:1901 +msgid "Running Nodes" +msgstr "Menjalankan Node" + +#: mod_configure.erl:504 web/ejabberd_web_admin.erl:1903 +msgid "Stopped Nodes" +msgstr "Menghentikan node" + +#: mod_configure.erl:577 mod_configure.erl:587 web/ejabberd_web_admin.erl:1947 +msgid "Modules" +msgstr "Modul" + +#: mod_configure.erl:578 +msgid "Backup Management" +msgstr "Manajemen Backup" + +#: mod_configure.erl:579 +msgid "Import Users From jabberd14 Spool Files" +msgstr "Impor Pengguna Dari jabberd14 Spool File" + +#: mod_configure.erl:699 +msgid "To ~s" +msgstr "Kepada ~s" + +#: mod_configure.erl:717 +msgid "From ~s" +msgstr "Dari ~s" + +#: mod_configure.erl:913 +msgid "Database Tables Configuration at " +msgstr "Database Tabel Konfigurasi pada" + +#: mod_configure.erl:918 +msgid "Choose storage type of tables" +msgstr "Pilih jenis penyimpanan tabel" + +#: mod_configure.erl:926 mod_configure.erl:928 +msgid "Disc only copy" +msgstr "Hanya salinan dari disc" + +#: mod_configure.erl:926 mod_configure.erl:928 +msgid "RAM and disc copy" +msgstr "RAM dan disc salinan" + +#: mod_configure.erl:926 mod_configure.erl:928 +msgid "RAM copy" +msgstr "Salinan RAM" + +#: mod_configure.erl:926 mod_configure.erl:928 +msgid "Remote copy" +msgstr "Salinan Remote" + +#: mod_configure.erl:950 +msgid "Stop Modules at " +msgstr "Hentikan Modul pada" + +#: mod_configure.erl:954 +msgid "Choose modules to stop" +msgstr "Pilih Modul untuk berhenti" + +#: mod_configure.erl:969 +msgid "Start Modules at " +msgstr "Mulai Modul pada" + +#: mod_configure.erl:973 +msgid "Enter list of {Module, [Options]}" +msgstr "Masukkan daftar {Modul, [Options]}" + +#: mod_configure.erl:974 +msgid "List of modules to start" +msgstr "Daftar modul untuk memulai" + +#: mod_configure.erl:983 +msgid "Backup to File at " +msgstr "Backup ke File pada" + +#: mod_configure.erl:987 mod_configure.erl:1001 +msgid "Enter path to backup file" +msgstr "Masukkan path untuk file cadangan" + +#: mod_configure.erl:988 mod_configure.erl:1002 mod_configure.erl:1016 +#: mod_configure.erl:1030 +msgid "Path to File" +msgstr "Jalur ke File" + +#: mod_configure.erl:997 +msgid "Restore Backup from File at " +msgstr "Kembalikan Backup dari File pada" + +#: mod_configure.erl:1011 +msgid "Dump Backup to Text File at " +msgstr "Dump Backup ke File Teks di" + +#: mod_configure.erl:1015 +msgid "Enter path to text file" +msgstr "Masukkan path ke file teks" + +#: mod_configure.erl:1025 +msgid "Import User from File at " +msgstr "Impor Pengguna dari File pada" + +#: mod_configure.erl:1029 +msgid "Enter path to jabberd14 spool file" +msgstr "Masukkan path ke file jabberd14 spool" + +#: mod_configure.erl:1039 +msgid "Import Users from Dir at " +msgstr "Impor Pengguna dari Dir di" + +#: mod_configure.erl:1043 +msgid "Enter path to jabberd14 spool dir" +msgstr "Masukkan path ke direktori spool jabberd14" + +#: mod_configure.erl:1044 +msgid "Path to Dir" +msgstr "Jalur ke Dir" + +#: mod_configure.erl:1060 mod_configure.erl:1105 +msgid "Time delay" +msgstr "Waktu tunda" + +#: mod_configure.erl:1143 +msgid "Access Control List Configuration" +msgstr "Konfigurasi Daftar Akses Pengendalian" + +#: mod_configure.erl:1147 +msgid "Access control lists" +msgstr "Daftar Pengendalian Akses" + +#: mod_configure.erl:1171 +msgid "Access Configuration" +msgstr "Akses Konfigurasi" + +#: mod_configure.erl:1175 +msgid "Access rules" +msgstr "Akses peraturan" + +#: mod_configure.erl:1200 mod_configure.erl:1222 mod_configure.erl:1234 +#: mod_configure.erl:1246 mod_configure.erl:1258 mod_configure.erl:1275 +#: mod_configure.erl:1287 mod_configure.erl:1652 mod_configure.erl:1702 +#: mod_configure.erl:1723 mod_roster.erl:948 mod_roster_odbc.erl:1048 +#: mod_vcard.erl:466 mod_vcard_ldap.erl:550 mod_vcard_odbc.erl:442 +msgid "Jabber ID" +msgstr "Jabber ID" + +#: mod_configure.erl:1205 mod_configure.erl:1263 mod_configure.erl:1653 +#: mod_configure.erl:1865 mod_muc/mod_muc_room.erl:2925 mod_register.erl:233 +#: web/ejabberd_web_admin.erl:1517 +msgid "Password" +msgstr "Sandi" + +#: mod_configure.erl:1210 +msgid "Password Verification" +msgstr "Verifikasi Sandi" + +#: mod_configure.erl:1301 +msgid "Number of registered users" +msgstr "Jumlah pengguna terdaftar" + +#: mod_configure.erl:1315 +msgid "Number of online users" +msgstr "Jumlah pengguna online" + +#: mod_configure.erl:1684 web/ejabberd_web_admin.erl:1585 +#: web/ejabberd_web_admin.erl:1737 +msgid "Never" +msgstr "Tidak Pernah" + +#: mod_configure.erl:1698 web/ejabberd_web_admin.erl:1598 +#: web/ejabberd_web_admin.erl:1750 +msgid "Online" +msgstr "Online" + +#: mod_configure.erl:1703 +msgid "Last login" +msgstr "Terakhir Login" + +#: mod_configure.erl:1724 +msgid "Roster size" +msgstr "Ukuran Daftar Kontak" + +#: mod_configure.erl:1725 +msgid "IP addresses" +msgstr "Alamat IP" + +#: mod_configure.erl:1726 +msgid "Resources" +msgstr "Sumber daya" + +#: mod_configure.erl:1852 +msgid "Administration of " +msgstr "Administrasi" + +#: mod_configure.erl:1855 +msgid "Action on user" +msgstr "Tindakan pada pengguna" + +#: mod_configure.erl:1859 +msgid "Edit Properties" +msgstr "Ganti Properti" + +#: mod_configure.erl:1862 web/ejabberd_web_admin.erl:1763 +msgid "Remove User" +msgstr "Hapus Pengguna" + +#: mod_irc/mod_irc.erl:201 mod_muc/mod_muc.erl:336 +msgid "Access denied by service policy" +msgstr "Akses ditolak oleh kebijakan layanan" + +#: mod_irc/mod_irc.erl:400 +msgid "IRC Transport" +msgstr "IRC Transport" + +#: mod_irc/mod_irc.erl:427 +msgid "ejabberd IRC module" +msgstr "ejabberd IRC modul" + +#: mod_irc/mod_irc.erl:558 +msgid "You need an x:data capable client to configure mod_irc settings" +msgstr "" +"Anda memerlukan x:data klien untuk mampu mengkonfigurasi pengaturan mod_irc" + +#: mod_irc/mod_irc.erl:565 +msgid "Registration in mod_irc for " +msgstr "Pendaftaran di mod_irc untuk" + +#: mod_irc/mod_irc.erl:570 +msgid "" +"Enter username, encodings, ports and passwords you wish to use for " +"connecting to IRC servers" +msgstr "" +"Masukkan username, pengkodean, port dan sandi yang ingin Anda gunakan untuk " +"menghubungkan ke layanan IRC" + +#: mod_irc/mod_irc.erl:575 +msgid "IRC Username" +msgstr "Nama Pengguna IRC" + +#: mod_irc/mod_irc.erl:585 +msgid "" +"If you want to specify different ports, passwords, encodings for IRC " +"servers, fill this list with values in format '{\"irc server\", \"encoding" +"\", port, \"password\"}'. By default this service use \"~s\" encoding, port " +"~p, empty password." +msgstr "" +"Jika Anda ingin menentukan port yang berbeda, sandi, pengkodean untuk " +"layanan IRC, isi daftar ini dengan nilai-nilai dalam format '{\"server irc " +"\", \"encoding \", port, \"sandi \"}'. Secara default ini menggunakan " +"layanan \"~s \" pengkodean, port ~p, kata sandi kosong." + +#: mod_irc/mod_irc.erl:597 +msgid "" +"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." +"net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." +msgstr "" +"Contoh: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." +"net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." + +#: mod_irc/mod_irc.erl:602 +msgid "Connections parameters" +msgstr "Parameter Koneksi" + +#: mod_irc/mod_irc.erl:727 +msgid "Join IRC channel" +msgstr "Gabung channel IRC" + +#: mod_irc/mod_irc.erl:731 +msgid "IRC channel (don't put the first #)" +msgstr "Channel IRC (tidak perlu menempatkan # sebelumnya)" + +#: mod_irc/mod_irc.erl:736 +msgid "IRC server" +msgstr "Layanan IRC" + +#: mod_irc/mod_irc.erl:769 mod_irc/mod_irc.erl:773 +msgid "Join the IRC channel here." +msgstr "Gabung ke channel IRC disini" + +#: mod_irc/mod_irc.erl:777 +msgid "Join the IRC channel in this Jabber ID: ~s" +msgstr "Gabung ke channel IRC dengan Jabber ID: ~s" + +#: mod_irc/mod_irc.erl:862 +msgid "IRC settings" +msgstr "Pengaturan IRC" + +#: mod_irc/mod_irc.erl:867 +msgid "" +"Enter username and encodings you wish to use for connecting to IRC servers. " +"Press 'Next' to get more fields to fill in. Press 'Complete' to save " +"settings." +msgstr "" +"Masukkan username dan pengkodean yang ingin Anda gunakan untuk menghubungkan " +"ke layanan IRC. Tekan 'Selanjutnya' untuk mendapatkan lagi formulir kemudian " +"Tekan 'Lengkap' untuk menyimpan pengaturan." + +#: mod_irc/mod_irc.erl:873 +msgid "IRC username" +msgstr "Nama Pengguna IRC" + +#: mod_irc/mod_irc.erl:922 +msgid "Password ~b" +msgstr "Kata Sandi ~b" + +#: mod_irc/mod_irc.erl:927 +msgid "Port ~b" +msgstr "Port ~b" + +#: mod_irc/mod_irc.erl:932 +msgid "Encoding for server ~b" +msgstr "Pengkodean untuk layanan ~b" + +#: mod_irc/mod_irc.erl:941 +msgid "Server ~b" +msgstr "Layanan ~b" + +#: mod_muc/mod_muc.erl:449 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Layanan hanya diperuntukan kepada administrator yang diizinkan untuk " +"mengirim layanan pesan" + +#: mod_muc/mod_muc.erl:493 +msgid "Room creation is denied by service policy" +msgstr "Pembuatan Ruangan ditolak oleh kebijakan layanan" + +#: mod_muc/mod_muc.erl:500 +msgid "Conference room does not exist" +msgstr "Ruang Konferensi tidak ada" + +#: mod_muc/mod_muc.erl:581 +msgid "Chatrooms" +msgstr "Ruangan Chat" + +#: mod_muc/mod_muc.erl:711 +msgid "You need a client that supports x:data to register the nickname" +msgstr "Anda memerlukan klien yang mendukung x:data untuk mendaftar julukan" + +#: mod_muc/mod_muc.erl:717 +msgid "Nickname Registration at " +msgstr "Pendaftaran Julukan pada" + +#: mod_muc/mod_muc.erl:721 +msgid "Enter nickname you want to register" +msgstr "Masukkan nama julukan Anda jika ingin mendaftar" + +#: mod_muc/mod_muc.erl:722 mod_roster.erl:949 mod_roster_odbc.erl:1049 +#: mod_vcard.erl:358 mod_vcard.erl:471 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:447 +msgid "Nickname" +msgstr "Nama Julukan" + +#: mod_muc/mod_muc.erl:761 mod_muc/mod_muc_room.erl:933 +#: mod_muc/mod_muc_room.erl:1577 +msgid "That nickname is registered by another person" +msgstr "Julukan tersebut telah didaftarkan oleh orang lain" + +#: mod_muc/mod_muc.erl:787 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Anda harus mengisi kolom \"Julukan\" dalam formulir" + +#: mod_muc/mod_muc.erl:807 +msgid "ejabberd MUC module" +msgstr "ejabberd MUC Module" + +#: mod_muc/mod_muc_log.erl:374 mod_muc/mod_muc_log.erl:381 +msgid "Chatroom configuration modified" +msgstr "Konfigurasi ruang chat diubah" + +#: mod_muc/mod_muc_log.erl:384 +msgid "joins the room" +msgstr "bergabung ke ruangan" + +#: mod_muc/mod_muc_log.erl:387 mod_muc/mod_muc_log.erl:390 +msgid "leaves the room" +msgstr "meninggalkan ruangan" + +#: mod_muc/mod_muc_log.erl:393 mod_muc/mod_muc_log.erl:396 +msgid "has been banned" +msgstr "telah dibanned" + +#: mod_muc/mod_muc_log.erl:399 mod_muc/mod_muc_log.erl:402 +msgid "has been kicked" +msgstr "telah dikick" + +#: mod_muc/mod_muc_log.erl:405 +msgid "has been kicked because of an affiliation change" +msgstr "telah dikick karena perubahan afiliasi" + +#: mod_muc/mod_muc_log.erl:408 +msgid "has been kicked because the room has been changed to members-only" +msgstr "telah dikick karena ruangan telah diubah menjadi hanya untuk member" + +#: mod_muc/mod_muc_log.erl:411 +msgid "has been kicked because of a system shutdown" +msgstr "telah dikick karena sistem shutdown" + +#: mod_muc/mod_muc_log.erl:414 +msgid "is now known as" +msgstr "sekarang dikenal sebagai" + +#: mod_muc/mod_muc_log.erl:417 mod_muc/mod_muc_log.erl:689 +#: mod_muc/mod_muc_room.erl:2112 +msgid " has set the subject to: " +msgstr "telah menetapkan topik yaitu:" + +#: mod_muc/mod_muc_log.erl:452 +msgid "Chatroom is created" +msgstr "Ruang chat telah dibuat" + +#: mod_muc/mod_muc_log.erl:453 +msgid "Chatroom is destroyed" +msgstr "Ruang chat dilenyapkan" + +#: mod_muc/mod_muc_log.erl:454 +msgid "Chatroom is started" +msgstr "Ruang chat dimulai" + +#: mod_muc/mod_muc_log.erl:455 +msgid "Chatroom is stopped" +msgstr "Ruang chat dihentikan" + +#: mod_muc/mod_muc_log.erl:459 +msgid "Monday" +msgstr "Senin" + +#: mod_muc/mod_muc_log.erl:460 +msgid "Tuesday" +msgstr "Selasa" + +#: mod_muc/mod_muc_log.erl:461 +msgid "Wednesday" +msgstr "Rabu" + +#: mod_muc/mod_muc_log.erl:462 +msgid "Thursday" +msgstr "Kamis" + +#: mod_muc/mod_muc_log.erl:463 +msgid "Friday" +msgstr "Jumat" + +#: mod_muc/mod_muc_log.erl:464 +msgid "Saturday" +msgstr "Sabtu" + +#: mod_muc/mod_muc_log.erl:465 +msgid "Sunday" +msgstr "Minggu" + +#: mod_muc/mod_muc_log.erl:469 +msgid "January" +msgstr "Januari" + +#: mod_muc/mod_muc_log.erl:470 +msgid "February" +msgstr "Februari" + +#: mod_muc/mod_muc_log.erl:471 +msgid "March" +msgstr "Maret" + +#: mod_muc/mod_muc_log.erl:472 +msgid "April" +msgstr "April" + +#: mod_muc/mod_muc_log.erl:473 +msgid "May" +msgstr "Mei" + +#: mod_muc/mod_muc_log.erl:474 +msgid "June" +msgstr "Juni" + +#: mod_muc/mod_muc_log.erl:475 +msgid "July" +msgstr "Juli" + +#: mod_muc/mod_muc_log.erl:476 +msgid "August" +msgstr "Agustus" + +#: mod_muc/mod_muc_log.erl:477 +msgid "September" +msgstr "September" + +#: mod_muc/mod_muc_log.erl:478 +msgid "October" +msgstr "Oktober" + +#: mod_muc/mod_muc_log.erl:479 +msgid "November" +msgstr "Nopember" + +#: mod_muc/mod_muc_log.erl:480 +msgid "December" +msgstr "Desember" + +#: mod_muc/mod_muc_log.erl:751 +msgid "Room Configuration" +msgstr "Konfigurasi Ruangan" + +#: mod_muc/mod_muc_log.erl:760 +msgid "Room Occupants" +msgstr "Penghuni Ruangan" + +#: mod_muc/mod_muc_room.erl:170 +msgid "Traffic rate limit is exceeded" +msgstr "Lalu lintas melebihi batas" + +#: mod_muc/mod_muc_room.erl:242 +msgid "" +"This participant is kicked from the room because he sent an error message" +msgstr "Peserta ini dikick dari ruangan karena dia mengirim pesan kesalahan" + +#: mod_muc/mod_muc_room.erl:251 +msgid "It is not allowed to send private messages to the conference" +msgstr "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi ke konferensi" + +#: mod_muc/mod_muc_room.erl:296 +msgid "Improper message type" +msgstr "Jenis pesan yang tidak benar" + +#: mod_muc/mod_muc_room.erl:406 +msgid "" +"This participant is kicked from the room because he sent an error message to " +"another participant" +msgstr "" +"Participant ini dikick dari ruangan karena ia mengirim pesan kesalahan ke " +"participant lain" + +#: mod_muc/mod_muc_room.erl:419 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" +"Hal ini tidak diperbolehkan untuk mengirim pesan pribadi jenis \"groupchat \"" + +#: mod_muc/mod_muc_room.erl:431 mod_muc/mod_muc_room.erl:486 +msgid "Recipient is not in the conference room" +msgstr "Penerima tidak berada di ruangan konferensi" + +#: mod_muc/mod_muc_room.erl:451 mod_muc/mod_muc_room.erl:829 +#: mod_muc/mod_muc_room.erl:3543 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Hanya penghuni yang diizinkan untuk mengirim pesan ke konferensi" + +#: mod_muc/mod_muc_room.erl:460 +msgid "It is not allowed to send private messages" +msgstr "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi" + +#: mod_muc/mod_muc_room.erl:509 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Hanya penghuni diizinkan untuk mengirim permintaan ke konferensi" + +#: mod_muc/mod_muc_room.erl:521 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Permintaan untuk para anggota konferensi tidak diperbolehkan di ruangan ini" + +#: mod_muc/mod_muc_room.erl:805 +msgid "" +"Only moderators and participants are allowed to change the subject in this " +"room" +msgstr "" +"Hanya moderator dan peserta yang diizinkan untuk mengganti topik pembicaraan " +"di ruangan ini" + +#: mod_muc/mod_muc_room.erl:810 +msgid "Only moderators are allowed to change the subject in this room" +msgstr "" +"Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini" + +#: mod_muc/mod_muc_room.erl:820 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Visitor tidak diperbolehkan untuk mengirim pesan ke semua penghuni" + +#: mod_muc/mod_muc_room.erl:891 +msgid "" +"This participant is kicked from the room because he sent an error presence" +msgstr "" +"Participant ini dikick dari ruangan karena ia mengirim kehadiran kesalahan" + +#: mod_muc/mod_muc_room.erl:909 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Visitor tidak diperbolehkan untuk mengubah nama julukan di ruangan ini" + +#: mod_muc/mod_muc_room.erl:922 mod_muc/mod_muc_room.erl:1569 +msgid "That nickname is already in use by another occupant" +msgstr "Julukan itu sudah digunakan oleh penghuni lain" + +#: mod_muc/mod_muc_room.erl:1558 +msgid "You have been banned from this room" +msgstr "Anda telah diblokir dari ruangan ini" + +#: mod_muc/mod_muc_room.erl:1561 +msgid "Membership is required to enter this room" +msgstr "Hanya Member yang dapat masuk ruangan ini" + +#: mod_muc/mod_muc_room.erl:1597 +msgid "This room is not anonymous" +msgstr "Ruangan ini tidak dikenal" + +#: mod_muc/mod_muc_room.erl:1623 +msgid "A password is required to enter this room" +msgstr "Diperlukan kata sandi untuk masuk ruangan ini" + +#: mod_muc/mod_muc_room.erl:1645 +msgid "Unable to generate a captcha" +msgstr "Tidak dapat menghasilkan captcha" + +#: mod_muc/mod_muc_room.erl:1655 +msgid "Incorrect password" +msgstr "Kata sandi salah" + +#: mod_muc/mod_muc_room.erl:2167 +msgid "Administrator privileges required" +msgstr "Hak istimewa Administrator dibutuhkan" + +#: mod_muc/mod_muc_room.erl:2182 +msgid "Moderator privileges required" +msgstr "Hak istimewa moderator dibutuhkan" + +#: mod_muc/mod_muc_room.erl:2337 +msgid "Jabber ID ~s is invalid" +msgstr "Jabber ID ~s tidak valid" + +#: mod_muc/mod_muc_room.erl:2351 +msgid "Nickname ~s does not exist in the room" +msgstr "Nama Julukan ~s tidak berada di dalam ruangan" + +#: mod_muc/mod_muc_room.erl:2377 mod_muc/mod_muc_room.erl:2759 +msgid "Invalid affiliation: ~s" +msgstr "Afiliasi tidak valid: ~s" + +#: mod_muc/mod_muc_room.erl:2434 +msgid "Invalid role: ~s" +msgstr "Peran tidak valid: ~s" + +#: mod_muc/mod_muc_room.erl:2736 mod_muc/mod_muc_room.erl:2772 +msgid "Owner privileges required" +msgstr "Hak istimewa owner dibutuhkan" + +#: mod_muc/mod_muc_room.erl:2896 +msgid "Configuration of room ~s" +msgstr "Pengaturan ruangan ~s" + +#: mod_muc/mod_muc_room.erl:2901 +msgid "Room title" +msgstr "Nama Ruangan" + +#: mod_muc/mod_muc_room.erl:2904 mod_muc/mod_muc_room.erl:3322 +msgid "Room description" +msgstr "Keterangan ruangan" + +#: mod_muc/mod_muc_room.erl:2911 +msgid "Make room persistent" +msgstr "Buat ruangan menjadi permanent" + +#: mod_muc/mod_muc_room.erl:2916 +msgid "Make room public searchable" +msgstr "Buat ruangan dapat dicari" + +#: mod_muc/mod_muc_room.erl:2919 +msgid "Make participants list public" +msgstr "Buat daftar participant diketahui oleh public" + +#: mod_muc/mod_muc_room.erl:2922 +msgid "Make room password protected" +msgstr "Buat ruangan yang dilindungi dengan kata sandi" + +#: mod_muc/mod_muc_room.erl:2933 +msgid "Maximum Number of Occupants" +msgstr "Maksimum Jumlah Penghuni" + +#: mod_muc/mod_muc_room.erl:2940 +msgid "No limit" +msgstr "Tidak terbatas" + +#: mod_muc/mod_muc_room.erl:2951 +msgid "Present real Jabber IDs to" +msgstr "Tampilkan Jabber ID secara lengkap" + +#: mod_muc/mod_muc_room.erl:2959 +msgid "moderators only" +msgstr "Hanya moderator" + +#: mod_muc/mod_muc_room.erl:2961 +msgid "anyone" +msgstr "Siapapun" + +#: mod_muc/mod_muc_room.erl:2963 +msgid "Make room members-only" +msgstr "Buat ruangan hanya untuk member saja" + +#: mod_muc/mod_muc_room.erl:2966 +msgid "Make room moderated" +msgstr "Buat ruangan hanya untuk moderator saja" + +#: mod_muc/mod_muc_room.erl:2969 +msgid "Default users as participants" +msgstr "pengguna pertama kali masuk sebagai participant" + +#: mod_muc/mod_muc_room.erl:2972 +msgid "Allow users to change the subject" +msgstr "Perbolehkan pengguna untuk mengganti topik" + +#: mod_muc/mod_muc_room.erl:2975 +msgid "Allow users to send private messages" +msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" + +#: mod_muc/mod_muc_room.erl:2978 +msgid "Allow users to query other users" +msgstr "Perbolehkan pengguna untuk mengetahui pengguna lain" + +#: mod_muc/mod_muc_room.erl:2981 +msgid "Allow users to send invites" +msgstr "Perbolehkan pengguna mengirimkan undangan" + +#: mod_muc/mod_muc_room.erl:2984 +msgid "Allow visitors to send status text in presence updates" +msgstr "Izinkan pengunjung untuk mengirim teks status terbaru" + +#: mod_muc/mod_muc_room.erl:2987 +msgid "Allow visitors to change nickname" +msgstr "Perbolehkan visitor mengganti nama julukan" + +#: mod_muc/mod_muc_room.erl:2993 +msgid "Make room captcha protected" +msgstr "Buat ruangan dilindungi dengan chapta" + +#: mod_muc/mod_muc_room.erl:3002 +msgid "Enable logging" +msgstr "Aktifkan catatan" + +#: mod_muc/mod_muc_room.erl:3010 +msgid "You need an x:data capable client to configure room" +msgstr "Anda memerlukan x:data klien untuk dapat mengkonfigurasi ruangan" + +#: mod_muc/mod_muc_room.erl:3324 +msgid "Number of occupants" +msgstr "Jumlah Penghuni" + +#: mod_muc/mod_muc_room.erl:3380 +msgid "private, " +msgstr "pribadi, " + +#: mod_muc/mod_muc_room.erl:3463 +msgid "~s invites you to the room ~s" +msgstr "~s mengundang anda ke ruangan ~s" + +#: mod_muc/mod_muc_room.erl:3472 +msgid "the password is" +msgstr "kata sandi yaitu:" + +#: mod_offline.erl:510 mod_offline_odbc.erl:352 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Kontak offline Anda pada antrian pesan sudah penuh. Pesan telah dibuang." + +#: mod_offline.erl:560 mod_offline_odbc.erl:408 +msgid "~s's Offline Messages Queue" +msgstr "Antrian Pesan Offline ~s" + +#: mod_offline.erl:563 mod_offline_odbc.erl:411 mod_roster.erl:992 +#: mod_roster_odbc.erl:1092 mod_shared_roster.erl:810 +#: mod_shared_roster.erl:911 web/ejabberd_web_admin.erl:829 +#: web/ejabberd_web_admin.erl:870 web/ejabberd_web_admin.erl:938 +#: web/ejabberd_web_admin.erl:974 web/ejabberd_web_admin.erl:1015 +#: web/ejabberd_web_admin.erl:1505 web/ejabberd_web_admin.erl:1754 +#: web/ejabberd_web_admin.erl:1925 web/ejabberd_web_admin.erl:1957 +#: web/ejabberd_web_admin.erl:2026 web/ejabberd_web_admin.erl:2130 +#: web/ejabberd_web_admin.erl:2155 web/ejabberd_web_admin.erl:2243 +msgid "Submitted" +msgstr "Ulangi masukan" + +#: mod_offline.erl:571 +msgid "Time" +msgstr "Waktu" + +#: mod_offline.erl:572 +msgid "From" +msgstr "Dari" + +#: mod_offline.erl:573 +msgid "To" +msgstr "Kepada" + +#: mod_offline.erl:574 mod_offline_odbc.erl:419 +msgid "Packet" +msgstr "Paket" + +#: mod_offline.erl:587 mod_offline_odbc.erl:432 mod_shared_roster.erl:817 +#: web/ejabberd_web_admin.erl:878 web/ejabberd_web_admin.erl:982 +msgid "Delete Selected" +msgstr "Hapus Yang Terpilih" + +#: mod_offline.erl:645 mod_offline_odbc.erl:519 +msgid "Offline Messages:" +msgstr "Pesan Offline:" + +#: mod_offline.erl:645 mod_offline_odbc.erl:519 +msgid "Remove All Offline Messages" +msgstr "Hapus Semua Pesan Offline" + +#: mod_proxy65/mod_proxy65_service.erl:213 +msgid "ejabberd SOCKS5 Bytestreams module" +msgstr "modul ejabberd SOCKS5 Bytestreams" + +#: mod_pubsub/mod_pubsub.erl:1119 mod_pubsub/mod_pubsub_odbc.erl:928 +msgid "Publish-Subscribe" +msgstr "Setujui-Pertemanan" + +#: mod_pubsub/mod_pubsub.erl:1213 mod_pubsub/mod_pubsub_odbc.erl:1024 +msgid "ejabberd Publish-Subscribe module" +msgstr "Modul ejabberd Setujui-Pertemanan" + +#: mod_pubsub/mod_pubsub.erl:1496 mod_pubsub/mod_pubsub_odbc.erl:1311 +msgid "PubSub subscriber request" +msgstr "Permintaan pertemanan PubSub" + +#: mod_pubsub/mod_pubsub.erl:1498 mod_pubsub/mod_pubsub_odbc.erl:1313 +msgid "Choose whether to approve this entity's subscription." +msgstr "Pilih apakah akan menyetujui hubungan pertemanan ini." + +#: mod_pubsub/mod_pubsub.erl:1504 mod_pubsub/mod_pubsub_odbc.erl:1319 +msgid "Node ID" +msgstr "ID Node" + +#: mod_pubsub/mod_pubsub.erl:1509 mod_pubsub/mod_pubsub_odbc.erl:1324 +msgid "Subscriber Address" +msgstr "Alamat Pertemanan" + +#: mod_pubsub/mod_pubsub.erl:1515 mod_pubsub/mod_pubsub_odbc.erl:1330 +msgid "Allow this Jabber ID to subscribe to this pubsub node?" +msgstr "Izinkan ID Jabber ini untuk berlangganan pada node pubsub ini?" + +#: mod_pubsub/mod_pubsub.erl:3387 mod_pubsub/mod_pubsub_odbc.erl:3229 +msgid "Deliver payloads with event notifications" +msgstr "Memberikan muatan dengan pemberitahuan acara" + +#: mod_pubsub/mod_pubsub.erl:3388 mod_pubsub/mod_pubsub_odbc.erl:3230 +msgid "Deliver event notifications" +msgstr "Memberikan pemberitahuan acara" + +#: mod_pubsub/mod_pubsub.erl:3389 mod_pubsub/mod_pubsub_odbc.erl:3231 +msgid "Notify subscribers when the node configuration changes" +msgstr "Beritahu pelanggan ketika ada perubahan konfigurasi node" + +#: mod_pubsub/mod_pubsub.erl:3390 mod_pubsub/mod_pubsub_odbc.erl:3232 +msgid "Notify subscribers when the node is deleted" +msgstr "Beritahu pelanggan ketika node dihapus" + +#: mod_pubsub/mod_pubsub.erl:3391 mod_pubsub/mod_pubsub_odbc.erl:3233 +msgid "Notify subscribers when items are removed from the node" +msgstr "Beritahu pelanggan ketika item tersebut dikeluarkan dari node" + +#: mod_pubsub/mod_pubsub.erl:3392 mod_pubsub/mod_pubsub_odbc.erl:3234 +msgid "Persist items to storage" +msgstr "Pertahankan item ke penyimpanan" + +#: mod_pubsub/mod_pubsub.erl:3393 mod_pubsub/mod_pubsub_odbc.erl:3235 +msgid "A friendly name for the node" +msgstr "Nama yang dikenal untuk node" + +#: mod_pubsub/mod_pubsub.erl:3394 mod_pubsub/mod_pubsub_odbc.erl:3236 +msgid "Max # of items to persist" +msgstr "Max item untuk bertahan" + +#: mod_pubsub/mod_pubsub.erl:3395 mod_pubsub/mod_pubsub_odbc.erl:3237 +msgid "Whether to allow subscriptions" +msgstr "Apakah diperbolehkan untuk berlangganan" + +#: mod_pubsub/mod_pubsub.erl:3396 mod_pubsub/mod_pubsub_odbc.erl:3238 +msgid "Specify the access model" +msgstr "Tentukan model akses" + +#: mod_pubsub/mod_pubsub.erl:3399 mod_pubsub/mod_pubsub_odbc.erl:3241 +msgid "Roster groups allowed to subscribe" +msgstr "Kelompok kontak yang diizinkan untuk berlangganan" + +#: mod_pubsub/mod_pubsub.erl:3400 mod_pubsub/mod_pubsub_odbc.erl:3242 +msgid "Specify the publisher model" +msgstr "Tentukan model penerbitan" + +#: mod_pubsub/mod_pubsub.erl:3402 mod_pubsub/mod_pubsub_odbc.erl:3244 +msgid "Purge all items when the relevant publisher goes offline" +msgstr "Bersihkan semua item ketika penerbit yang relevan telah offline" + +#: mod_pubsub/mod_pubsub.erl:3403 mod_pubsub/mod_pubsub_odbc.erl:3245 +msgid "Specify the event message type" +msgstr "Tentukan jenis acara pesan" + +#: mod_pubsub/mod_pubsub.erl:3405 mod_pubsub/mod_pubsub_odbc.erl:3247 +msgid "Max payload size in bytes" +msgstr "Max kapasitas ukuran dalam bytes" + +#: mod_pubsub/mod_pubsub.erl:3406 mod_pubsub/mod_pubsub_odbc.erl:3248 +msgid "When to send the last published item" +msgstr "Ketika untuk mengirim item terakhir yang dipublikasikan" + +#: mod_pubsub/mod_pubsub.erl:3408 mod_pubsub/mod_pubsub_odbc.erl:3250 +msgid "Only deliver notifications to available users" +msgstr "Hanya mengirimkan pemberitahuan kepada pengguna yang tersedia" + +#: mod_pubsub/mod_pubsub.erl:3409 mod_pubsub/mod_pubsub_odbc.erl:3251 +msgid "The collections with which a node is affiliated" +msgstr "Koleksi dengan yang berafiliasi dengan sebuah node" + +#: mod_register.erl:191 +msgid "The CAPTCHA verification has failed" +msgstr "Verifikasi CAPTCHA telah gagal" + +#: mod_register.erl:218 +msgid "You need a client that supports x:data and CAPTCHA to register" +msgstr "" +"Anda memerlukan klien yang mendukung x:data dan CAPTCHA untuk mendaftar" + +#: mod_register.erl:224 mod_register.erl:258 +msgid "Choose a username and password to register with this server" +msgstr "Pilih nama pengguna dan kata sandi untuk mendaftar dengan layanan ini" + +#: mod_register.erl:228 mod_vcard.erl:358 mod_vcard_odbc.erl:336 +#: web/ejabberd_web_admin.erl:1512 web/ejabberd_web_admin.erl:1569 +msgid "User" +msgstr "Pengguna" + +#: mod_register.erl:244 +msgid "Unable to generate a CAPTCHA" +msgstr "Tidak dapat menghasilkan CAPTCHA" + +#: mod_register.erl:309 mod_register.erl:354 +msgid "The password is too weak" +msgstr "Kata sandi terlalu lemah" + +#: mod_register.erl:358 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Pengguna tidak diperkenankan untuk mendaftar akun begitu cepat" + +#: mod_roster.erl:943 mod_roster_odbc.erl:1043 web/ejabberd_web_admin.erl:1695 +#: web/ejabberd_web_admin.erl:1880 web/ejabberd_web_admin.erl:1891 +#: web/ejabberd_web_admin.erl:2214 +msgid "None" +msgstr "Tak satupun" + +#: mod_roster.erl:950 mod_roster_odbc.erl:1050 +msgid "Subscription" +msgstr "Berlangganan" + +#: mod_roster.erl:951 mod_roster_odbc.erl:1051 +msgid "Pending" +msgstr "Tertunda" + +#: mod_roster.erl:952 mod_roster_odbc.erl:1052 +msgid "Groups" +msgstr "Grup" + +#: mod_roster.erl:979 mod_roster_odbc.erl:1079 +msgid "Validate" +msgstr "Mengesahkan" + +#: mod_roster.erl:987 mod_roster_odbc.erl:1087 +msgid "Remove" +msgstr "Menghapus" + +#: mod_roster.erl:990 mod_roster_odbc.erl:1090 +msgid "Roster of " +msgstr "Kontak dari" + +#: mod_roster.erl:993 mod_roster_odbc.erl:1093 mod_shared_roster.erl:811 +#: mod_shared_roster.erl:912 web/ejabberd_web_admin.erl:830 +#: web/ejabberd_web_admin.erl:871 web/ejabberd_web_admin.erl:939 +#: web/ejabberd_web_admin.erl:975 web/ejabberd_web_admin.erl:1016 +#: web/ejabberd_web_admin.erl:1506 web/ejabberd_web_admin.erl:1755 +#: web/ejabberd_web_admin.erl:1926 web/ejabberd_web_admin.erl:2131 +#: web/ejabberd_web_admin.erl:2156 +msgid "Bad format" +msgstr "Format yang buruk" + +#: mod_roster.erl:1000 mod_roster_odbc.erl:1100 +msgid "Add Jabber ID" +msgstr "Tambah Jabber ID" + +#: mod_roster.erl:1099 mod_roster_odbc.erl:1199 +msgid "Roster" +msgstr "Kontak" + +#: mod_shared_roster.erl:766 mod_shared_roster.erl:808 +#: mod_shared_roster.erl:908 +msgid "Shared Roster Groups" +msgstr "Berbagi grup kontak" + +#: mod_shared_roster.erl:804 web/ejabberd_web_admin.erl:1362 +#: web/ejabberd_web_admin.erl:2456 +msgid "Add New" +msgstr "Tambah Baru" + +#: mod_shared_roster.erl:879 +msgid "Name:" +msgstr "Nama:" + +#: mod_shared_roster.erl:884 +msgid "Description:" +msgstr "Keterangan:" + +#: mod_shared_roster.erl:892 +msgid "Members:" +msgstr "Anggota:" + +#: mod_shared_roster.erl:900 +msgid "Displayed Groups:" +msgstr "Tampilkan Grup:" + +#: mod_shared_roster.erl:909 +msgid "Group " +msgstr "Grup" + +#: mod_shared_roster.erl:918 web/ejabberd_web_admin.erl:836 +#: web/ejabberd_web_admin.erl:880 web/ejabberd_web_admin.erl:945 +#: web/ejabberd_web_admin.erl:1022 web/ejabberd_web_admin.erl:2011 +msgid "Submit" +msgstr "Serahkan" + +#: mod_vcard.erl:165 mod_vcard_ldap.erl:237 mod_vcard_odbc.erl:129 +msgid "Erlang Jabber Server" +msgstr "Layanan Erlang Jabber" + +#: mod_vcard.erl:358 mod_vcard.erl:472 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:448 +msgid "Birthday" +msgstr "Hari Lahir" + +#: mod_vcard.erl:358 mod_vcard.erl:474 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:450 +msgid "City" +msgstr "Kota" + +#: mod_vcard.erl:358 mod_vcard.erl:473 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:449 +msgid "Country" +msgstr "Negara" + +#: mod_vcard.erl:358 mod_vcard.erl:475 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:451 +msgid "Email" +msgstr "Email" + +#: mod_vcard.erl:358 mod_vcard.erl:470 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:446 +msgid "Family Name" +msgstr "Nama Keluarga (marga)" + +#: mod_vcard.erl:358 mod_vcard_odbc.erl:336 +msgid "" +"Fill in the form to search for any matching Jabber User (Add * to the end of " +"field to match substring)" +msgstr "" +"Isi formulir untuk pencarian pengguna Jabber yang cocok (Tambahkan * ke " +"mengakhiri pengisian untuk menyamakan kata)" + +#: mod_vcard.erl:358 mod_vcard.erl:467 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:443 +msgid "Full Name" +msgstr "Nama Lengkap" + +#: mod_vcard.erl:358 mod_vcard.erl:469 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:445 +msgid "Middle Name" +msgstr "Nama Tengah" + +#: mod_vcard.erl:358 mod_vcard.erl:468 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:444 web/ejabberd_web_admin.erl:2000 +msgid "Name" +msgstr "Nama" + +#: mod_vcard.erl:358 mod_vcard.erl:476 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:452 +msgid "Organization Name" +msgstr "Nama Organisasi" + +#: mod_vcard.erl:358 mod_vcard.erl:477 mod_vcard_odbc.erl:336 +#: mod_vcard_odbc.erl:453 +msgid "Organization Unit" +msgstr "Unit Organisasi" + +#: mod_vcard.erl:358 mod_vcard_ldap.erl:458 mod_vcard_odbc.erl:336 +msgid "Search users in " +msgstr "Pencarian pengguna dalam" + +#: mod_vcard.erl:358 mod_vcard_ldap.erl:458 mod_vcard_odbc.erl:336 +msgid "You need an x:data capable client to search" +msgstr "Anda memerlukan x:data klien untuk melakukan pencarian" + +#: mod_vcard.erl:383 mod_vcard_ldap.erl:483 mod_vcard_odbc.erl:361 +msgid "vCard User Search" +msgstr "vCard Pencarian Pengguna" + +#: mod_vcard.erl:439 mod_vcard_ldap.erl:537 mod_vcard_odbc.erl:415 +msgid "ejabberd vCard module" +msgstr "Modul ejabberd vCard" + +#: mod_vcard.erl:463 mod_vcard_ldap.erl:547 mod_vcard_odbc.erl:439 +msgid "Search Results for " +msgstr "Hasil Pencarian untuk" + +#: mod_vcard_ldap.erl:458 +msgid "Fill in fields to search for any matching Jabber User" +msgstr "Isi kolom untuk mencari pengguna Jabber yang sama" + +#: web/ejabberd_web_admin.erl:189 web/ejabberd_web_admin.erl:199 +#: web/ejabberd_web_admin.erl:215 web/ejabberd_web_admin.erl:225 +msgid "Unauthorized" +msgstr "Ditolak" + +#: web/ejabberd_web_admin.erl:282 web/ejabberd_web_admin.erl:299 +msgid "ejabberd Web Admin" +msgstr "Admin Web ejabberd" + +#: web/ejabberd_web_admin.erl:765 web/ejabberd_web_admin.erl:776 +msgid "Administration" +msgstr "Administrasi" + +#: web/ejabberd_web_admin.erl:874 web/ejabberd_web_admin.erl:978 +msgid "Raw" +msgstr "mentah" + +#: web/ejabberd_web_admin.erl:1013 +msgid "~s access rule configuration" +msgstr "~s aturan akses konfigurasi" + +#: web/ejabberd_web_admin.erl:1031 +msgid "ejabberd virtual hosts" +msgstr "ejabberd virtual hosts" + +#: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 +msgid "Users" +msgstr "Pengguna" + +#: web/ejabberd_web_admin.erl:1074 +msgid "Users Last Activity" +msgstr "Aktifitas terakhir para pengguna" + +#: web/ejabberd_web_admin.erl:1076 +msgid "Period: " +msgstr "Periode:" + +#: web/ejabberd_web_admin.erl:1086 +msgid "Last month" +msgstr "Akhir bulan" + +#: web/ejabberd_web_admin.erl:1087 +msgid "Last year" +msgstr "Akhir tahun" + +#: web/ejabberd_web_admin.erl:1088 +msgid "All activity" +msgstr "Semua aktifitas" + +#: web/ejabberd_web_admin.erl:1090 +msgid "Show Ordinary Table" +msgstr "Tampilkan Tabel Normal" + +#: web/ejabberd_web_admin.erl:1092 +msgid "Show Integral Table" +msgstr "Tampilkan Tabel Terpisah" + +#: web/ejabberd_web_admin.erl:1101 web/ejabberd_web_admin.erl:1933 +msgid "Statistics" +msgstr "Statistik" + +#: web/ejabberd_web_admin.erl:1113 +msgid "Not Found" +msgstr "Tidak Ditemukan" + +#: web/ejabberd_web_admin.erl:1130 +msgid "Node not found" +msgstr "Node tidak ditemukan" + +#: web/ejabberd_web_admin.erl:1457 +msgid "Host" +msgstr "Host" + +#: web/ejabberd_web_admin.erl:1458 +msgid "Registered Users" +msgstr "Pengguna Terdaftar" + +#: web/ejabberd_web_admin.erl:1570 +msgid "Offline Messages" +msgstr "Pesan Offline" + +#: web/ejabberd_web_admin.erl:1571 web/ejabberd_web_admin.erl:1761 +msgid "Last Activity" +msgstr "Aktifitas Terakhir" + +#: web/ejabberd_web_admin.erl:1653 web/ejabberd_web_admin.erl:1669 +msgid "Registered Users:" +msgstr "Pengguna Terdaftar:" + +#: web/ejabberd_web_admin.erl:1655 web/ejabberd_web_admin.erl:1671 +#: web/ejabberd_web_admin.erl:2187 +msgid "Online Users:" +msgstr "Pengguna Online:" + +#: web/ejabberd_web_admin.erl:1657 +msgid "Outgoing s2s Connections:" +msgstr "Koneksi s2s yang keluar:" + +#: web/ejabberd_web_admin.erl:1659 +msgid "Outgoing s2s Servers:" +msgstr "Layanan s2s yang keluar:" + +#: web/ejabberd_web_admin.erl:1728 web/mod_register_web.erl:174 +#: web/mod_register_web.erl:367 web/mod_register_web.erl:376 +#: web/mod_register_web.erl:406 +msgid "Change Password" +msgstr "Ubah Kata Sandi" + +#: web/ejabberd_web_admin.erl:1752 +msgid "User " +msgstr "Pengguna" + +#: web/ejabberd_web_admin.erl:1759 +msgid "Connected Resources:" +msgstr "Sumber Daya Terhubung:" + +#: web/ejabberd_web_admin.erl:1760 web/mod_register_web.erl:226 +#: web/mod_register_web.erl:514 +msgid "Password:" +msgstr "Kata Sandi:" + +#: web/ejabberd_web_admin.erl:1822 +msgid "No Data" +msgstr "Tidak Ada Data" + +#: web/ejabberd_web_admin.erl:1900 +msgid "Nodes" +msgstr "Node-node" + +#: web/ejabberd_web_admin.erl:1923 web/ejabberd_web_admin.erl:1945 +msgid "Node " +msgstr "Node" + +#: web/ejabberd_web_admin.erl:1932 +msgid "Listened Ports" +msgstr "Port Terdeteksi" + +#: web/ejabberd_web_admin.erl:1934 web/ejabberd_web_admin.erl:2255 +#: web/ejabberd_web_admin.erl:2443 +msgid "Update" +msgstr "Memperbarui" + +#: web/ejabberd_web_admin.erl:1937 web/ejabberd_web_admin.erl:2564 +msgid "Restart" +msgstr "Jalankan Ulang" + +#: web/ejabberd_web_admin.erl:1939 web/ejabberd_web_admin.erl:2566 +msgid "Stop" +msgstr "Hentikan" + +#: web/ejabberd_web_admin.erl:1953 +msgid "RPC Call Error" +msgstr "Panggilan Kesalahan RPC" + +#: web/ejabberd_web_admin.erl:1994 +msgid "Database Tables at " +msgstr "Tabel Database pada" + +#: web/ejabberd_web_admin.erl:2001 +msgid "Storage Type" +msgstr "Jenis Penyimpanan" + +#: web/ejabberd_web_admin.erl:2002 +msgid "Elements" +msgstr "Elemen-elemen" + +#: web/ejabberd_web_admin.erl:2003 +msgid "Memory" +msgstr "Memori" + +#: web/ejabberd_web_admin.erl:2027 web/ejabberd_web_admin.erl:2132 +msgid "Error" +msgstr "Kesalahan" + +#: web/ejabberd_web_admin.erl:2029 +msgid "Backup of " +msgstr "Cadangan dari" + +#: web/ejabberd_web_admin.erl:2031 +msgid "" +"Please note that these options will only backup the builtin Mnesia database. " +"If you are using the ODBC module, you also need to backup your SQL database " +"separately." +msgstr "" +"Harap dicatat bahwa pilihan ini hanya akan membuat cadangan builtin Mnesia " +"database. Jika Anda menggunakan modul ODBC, anda juga perlu untuk membuat " +"cadangan database SQL Anda secara terpisah." + +#: web/ejabberd_web_admin.erl:2036 +msgid "Store binary backup:" +msgstr "Penyimpanan cadangan yang berpasangan:" + +#: web/ejabberd_web_admin.erl:2040 web/ejabberd_web_admin.erl:2047 +#: web/ejabberd_web_admin.erl:2055 web/ejabberd_web_admin.erl:2062 +#: web/ejabberd_web_admin.erl:2069 web/ejabberd_web_admin.erl:2076 +#: web/ejabberd_web_admin.erl:2083 web/ejabberd_web_admin.erl:2091 +#: web/ejabberd_web_admin.erl:2098 web/ejabberd_web_admin.erl:2105 +msgid "OK" +msgstr "YA" + +#: web/ejabberd_web_admin.erl:2043 +msgid "Restore binary backup immediately:" +msgstr "Segera mengembalikan cadangan yang berpasangan:" + +#: web/ejabberd_web_admin.erl:2051 +msgid "" +"Restore binary backup after next ejabberd restart (requires less memory):" +msgstr "" +"Mengembalikan cadangan yang berpasanagn setelah ejabberd berikutnya " +"dijalankan ulang (memerlukan memori lebih sedikit):" + +#: web/ejabberd_web_admin.erl:2058 +msgid "Store plain text backup:" +msgstr "Simpan cadangan teks biasa:" + +#: web/ejabberd_web_admin.erl:2065 +msgid "Restore plain text backup immediately:" +msgstr "Segera mengembalikan cadangan teks biasa:" + +#: web/ejabberd_web_admin.erl:2072 +msgid "Import users data from a PIEFXIS file (XEP-0227):" +msgstr "impor data-data pengguna dari sebuah PIEFXIS (XEP-0227):" + +#: web/ejabberd_web_admin.erl:2079 +msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" +msgstr "" +"Ekspor data dari semua pengguna pada layanan ke berkas PIEFXIS (XEP-0227):" + +#: web/ejabberd_web_admin.erl:2086 +msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" +msgstr "Ekspor data pengguna pada sebuah host ke berkas PIEFXIS (XEP-0227):" + +#: web/ejabberd_web_admin.erl:2094 +msgid "Import user data from jabberd14 spool file:" +msgstr "Impor data pengguna dari sekumpulan berkas jabberd14:" + +#: web/ejabberd_web_admin.erl:2101 +msgid "Import users data from jabberd14 spool directory:" +msgstr "Импорт пользовательских данных из буферной директории jabberd14:" + +#: web/ejabberd_web_admin.erl:2127 +msgid "Listened Ports at " +msgstr "Mendeteksi Port-port di" + +#: web/ejabberd_web_admin.erl:2152 +msgid "Modules at " +msgstr "modul-modul di" + +#: web/ejabberd_web_admin.erl:2178 +msgid "Statistics of ~p" +msgstr "statistik dari ~p" + +#: web/ejabberd_web_admin.erl:2181 +msgid "Uptime:" +msgstr "Sampai saat:" + +#: web/ejabberd_web_admin.erl:2184 +msgid "CPU Time:" +msgstr "Waktu CPU:" + +#: web/ejabberd_web_admin.erl:2190 +msgid "Transactions Committed:" +msgstr "Transaksi yang dilakukan:" + +#: web/ejabberd_web_admin.erl:2193 +msgid "Transactions Aborted:" +msgstr "Transaksi yang dibatalkan:" + +#: web/ejabberd_web_admin.erl:2196 +msgid "Transactions Restarted:" +msgstr "Transaksi yang dijalankan ulang:" + +#: web/ejabberd_web_admin.erl:2199 +msgid "Transactions Logged:" +msgstr "Transaksi yang ditempuh:" + +#: web/ejabberd_web_admin.erl:2241 +msgid "Update " +msgstr "Memperbarui " + +#: web/ejabberd_web_admin.erl:2249 +msgid "Update plan" +msgstr "Rencana Perubahan" + +#: web/ejabberd_web_admin.erl:2250 +msgid "Modified modules" +msgstr "Modifikasi modul-modul" + +#: web/ejabberd_web_admin.erl:2251 +msgid "Update script" +msgstr "Perbarui naskah" + +#: web/ejabberd_web_admin.erl:2252 +msgid "Low level update script" +msgstr "Perbaruan naskah tingkat rendah" + +#: web/ejabberd_web_admin.erl:2253 +msgid "Script check" +msgstr "Periksa naskah" + +#: web/ejabberd_web_admin.erl:2421 +msgid "Port" +msgstr "Port" + +#: web/ejabberd_web_admin.erl:2422 +msgid "IP" +msgstr "IP" + +#: web/ejabberd_web_admin.erl:2423 +msgid "Protocol" +msgstr "Protocol" + +#: web/ejabberd_web_admin.erl:2424 web/ejabberd_web_admin.erl:2551 +msgid "Module" +msgstr "Modul" + +#: web/ejabberd_web_admin.erl:2425 web/ejabberd_web_admin.erl:2552 +msgid "Options" +msgstr "Pilihan-pilihan" + +#: web/ejabberd_web_admin.erl:2445 +msgid "Delete" +msgstr "Hapus" + +#: web/ejabberd_web_admin.erl:2574 +msgid "Start" +msgstr "Mulai" + +#: web/mod_register_web.erl:103 +msgid "Your Jabber account was successfully created." +msgstr "Jabber akun Anda telah sukses dibuat" + +#: web/mod_register_web.erl:106 +msgid "There was an error creating the account: " +msgstr "Ada kesalahan saat membuat akun:" + +#: web/mod_register_web.erl:114 +msgid "Your Jabber account was successfully deleted." +msgstr "Jabber akun Anda berhasil dihapus." + +#: web/mod_register_web.erl:117 +msgid "There was an error deleting the account: " +msgstr "Ada kesalahan saat menghapus akun:" + +#: web/mod_register_web.erl:127 +msgid "The password of your Jabber account was successfully changed." +msgstr "Kata sandi pada akun Jabber Anda telah berhasil diubah." + +#: web/mod_register_web.erl:130 +msgid "There was an error changing the password: " +msgstr "Ada kesalahan dalam mengubah password:" + +#: web/mod_register_web.erl:162 web/mod_register_web.erl:171 +msgid "Jabber Account Registration" +msgstr "Pendaftaran Akun Jabber" + +#: web/mod_register_web.erl:173 web/mod_register_web.erl:191 +#: web/mod_register_web.erl:200 +msgid "Register a Jabber account" +msgstr "Daftarkan sebuah akun jabber" + +#: web/mod_register_web.erl:175 web/mod_register_web.erl:488 +#: web/mod_register_web.erl:497 +msgid "Unregister a Jabber account" +msgstr "Nonaktifkan akun jabber" + +#: web/mod_register_web.erl:202 +msgid "" +"This page allows to create a Jabber account in this Jabber server. Your JID " +"(Jabber IDentifier) will be of the form: username@server. Please read " +"carefully the instructions to fill correctly the fields." +msgstr "" +"Halaman ini memungkinkan untuk membuat akun Jabber di layanan Jabber ini. " +"JID Anda (Jabber Pengenal) akan berbentuk: namapengguna@layanan. Harap baca " +"dengan seksama petunjuk-petunjuk untuk mengisi kolom dengan benar." + +#: web/mod_register_web.erl:211 web/mod_register_web.erl:381 +#: web/mod_register_web.erl:504 +msgid "Username:" +msgstr "Nama Pengguna:" + +#: web/mod_register_web.erl:216 +msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." +msgstr "" +"Pada bagian ini huruf besar dan kecil tidak dibedakan: Misalnya macbeth " +"adalah sama dengan MacBeth juga Macbeth." + +#: web/mod_register_web.erl:217 +msgid "Characters not allowed:" +msgstr "Karakter tidak diperbolehkan:" + +#: web/mod_register_web.erl:221 web/mod_register_web.erl:386 +#: web/mod_register_web.erl:509 +msgid "Server:" +msgstr "Layanan:" + +#: web/mod_register_web.erl:231 +msgid "" +"Don't tell your password to anybody, not even the administrators of the " +"Jabber server." +msgstr "" +"Jangan memberitahukan kata sandi Anda ke siapapun, bahkan para administrator " +"dari layanan Jabber." + +#: web/mod_register_web.erl:233 +msgid "You can later change your password using a Jabber client." +msgstr "" +"Anda dapat mengubah kata sandi anda dilain waktu dengan menggunakan klien " +"Jabber." + +#: web/mod_register_web.erl:234 +msgid "" +"Some Jabber clients can store your password in your computer. Use that " +"feature only if you trust your computer is safe." +msgstr "" +"Beberapa klien Jabber dapat menyimpan password di komputer Anda. Gunakan " +"fitur itu hanya jika Anda mempercayai komputer Anda aman." + +#: web/mod_register_web.erl:236 +msgid "" +"Memorize your password, or write it in a paper placed in a safe place. In " +"Jabber there isn't an automated way to recover your password if you forget " +"it." +msgstr "" +"Hafalkan kata sandi Anda, atau dicatat dan letakkan di tempat yang aman. " +"Didalam Jabber tidak ada cara otomatis untuk mendapatkan kembali password " +"Anda jika Anda lupa." + +#: web/mod_register_web.erl:241 web/mod_register_web.erl:401 +msgid "Password Verification:" +msgstr "Verifikasi Kata Sandi:" + +#: web/mod_register_web.erl:249 +msgid "Register" +msgstr "Mendaftar" + +#: web/mod_register_web.erl:391 +msgid "Old Password:" +msgstr "Password Lama:" + +#: web/mod_register_web.erl:396 +msgid "New Password:" +msgstr "Password Baru:" + +#: web/mod_register_web.erl:499 +msgid "This page allows to unregister a Jabber account in this Jabber server." +msgstr "" +"Pada bagian ini memungkinkan Anda untuk membatalkan pendaftaran akun Jabber " +"pada layanan Jabber ini." + +#: web/mod_register_web.erl:519 +msgid "Unregister" +msgstr "Nonaktifkan" + +#, fuzzy +#~ msgid "Captcha test failed" +#~ msgstr "Проверка капчи прошла успешно." From fe40a9c5f63a1a17235f32d7eaacbc5e1f9cd476 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 16 Feb 2011 23:53:29 +0100 Subject: [PATCH 02/47] New DIST_USE_INTERFACE to restrict IP where erlang connections are listened (EJAB-1404) --- doc/guide.tex | 9 +++++++++ src/ejabberdctl.cfg.example | 11 +++++++++++ src/ejabberdctl.template | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/doc/guide.tex b/doc/guide.tex index d8afbabd7..e0bb42e4c 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -4990,6 +4990,9 @@ The command line parameters: If using \term{-sname}, specify either this option or \term{ERL\_INETRC}. \titem{-kernel inet\_dist\_listen\_min 4200 inet\_dist\_listen\_min 4210} Define the first and last ports that \term{epmd} (section \ref{epmd}) can listen to. + \titem{-kernel inet\_dist\_use\_interface "\{ 127,0,0,1 \}"} + Define the IP address where this Erlang node listens for other nodes + connections (see section \ref{epmd}). \titem{-detached} Starts the Erlang system detached from the system console. Useful for running daemons and backgrounds processes. @@ -5402,6 +5405,12 @@ The Erlang command-line parameter used internally is, for example: \begin{verbatim} erl ... -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375 \end{verbatim} +It is also possible to configure in \term{ejabberdctl.cfg} +the network interface where the Erlang node will listen and accept connections. +The Erlang command-line parameter used internally is, for example: +\begin{verbatim} +erl ... -kernel inet_dist_use_interface "{127,0,0,1}" +\end{verbatim} \makesection{cookie}{Erlang Cookie} diff --git a/src/ejabberdctl.cfg.example b/src/ejabberdctl.cfg.example index 4a3db1c8b..fe703242e 100644 --- a/src/ejabberdctl.cfg.example +++ b/src/ejabberdctl.cfg.example @@ -50,6 +50,17 @@ # #FIREWALL_WINDOW= +#. +#' INET_DIST_INTERFACE: IP address where this Erlang node listens other nodes +# +# This communication is used by ejabberdctl command line tool, +# and in a cluster of several ejabberd nodes. +# Notice that the IP address must be specified in the Erlang syntax. +# +# Default: {127,0,0,1} +# +INET_DIST_INTERFACE={127,0,0,1} + #. #' ERL_PROCESSES: Maximum number of Erlang processes # diff --git a/src/ejabberdctl.template b/src/ejabberdctl.template index a21c6527c..f12a12482 100644 --- a/src/ejabberdctl.template +++ b/src/ejabberdctl.template @@ -82,6 +82,10 @@ else KERNEL_OPTS="-kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" fi +if [ "$INET_DIST_INTERFACE" != "" ] ; then + KERNEL_OPTS+="-kernel inet_dist_use_interface \"${INET_DIST_INTERFACE}\"" +fi + ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" # define additional environment variables From 1c899143822feeeb95097774b81a5e8cb31829da Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 21 Feb 2011 13:44:30 +0100 Subject: [PATCH 03/47] New route_iq/5 accepting Timeout (thanks to Edwin Fine)(EJAB-1398) Also new register_iq_response_handler/5 --- src/ejabberd_local.erl | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 0cfc97b32..1ff0f48be 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -34,10 +34,12 @@ -export([route/3, route_iq/4, + route_iq/5, process_iq_reply/3, register_iq_handler/4, register_iq_handler/5, register_iq_response_handler/4, + register_iq_response_handler/5, unregister_iq_handler/2, unregister_iq_response_handler/2, refresh_iq_handlers/0, @@ -123,19 +125,31 @@ route(From, To, Packet) -> ok end. -route_iq(From, To, #iq{type = Type} = IQ, F) when is_function(F) -> +route_iq(From, To, IQ, F) -> + route_iq(From, To, IQ, F, undefined). + +route_iq(From, To, #iq{type = Type} = IQ, F, Timeout) when is_function(F) -> Packet = if Type == set; Type == get -> ID = randoms:get_string(), Host = From#jid.lserver, - register_iq_response_handler(Host, ID, undefined, F), + register_iq_response_handler(Host, ID, undefined, F, Timeout), jlib:iq_to_xml(IQ#iq{id = ID}); true -> jlib:iq_to_xml(IQ) end, ejabberd_router:route(From, To, Packet). -register_iq_response_handler(_Host, ID, Module, Function) -> - TRef = erlang:start_timer(?IQ_TIMEOUT, ejabberd_local, ID), +register_iq_response_handler(Host, ID, Module, Function) -> + register_iq_response_handler(Host, ID, Module, Function, undefined). + +register_iq_response_handler(_Host, ID, Module, Function, Timeout0) -> + Timeout = case Timeout0 of + undefined -> + ?IQ_TIMEOUT; + N when is_integer(N), N > 0 -> + N + end, + TRef = erlang:start_timer(Timeout, ejabberd_local, ID), mnesia:dirty_write(#iq_response{id = ID, module = Module, function = Function, From 850218c2df808d9802d960f09c513896b6b06560 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 21 Feb 2011 16:13:41 +0100 Subject: [PATCH 04/47] =?UTF-8?q?Forward=20old=20messages=20to=20newly=20s?= =?UTF-8?q?pawned=20extauth=20process=20(thanks=20to=20Mika=20Sepp=C3=A4ne?= =?UTF-8?q?n)(EJAB-1385)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/extauth.erl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/extauth.erl b/src/extauth.erl index c1721a0ef..3b2e7db64 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -126,7 +126,8 @@ loop(Port, Timeout, ProcessName, ExtPrg) -> ?ERROR_MSG("extauth call '~p' didn't receive response", [Msg]), Caller ! {eauth, false}, unregister(ProcessName), - spawn(?MODULE, init, [ProcessName, ExtPrg]), + Pid = spawn(?MODULE, init, [ProcessName, ExtPrg]), + flush_buffer_and_forward_messages(Pid), exit(port_terminated) end; stop -> @@ -140,6 +141,15 @@ loop(Port, Timeout, ProcessName, ExtPrg) -> exit(port_terminated) end. +flush_buffer_and_forward_messages(Pid) -> + receive + Message -> + Pid ! Message, + flush_buffer_and_forward_messages(Pid) + after 0 -> + true + end. + join(List, Sep) -> lists:foldl(fun(A, "") -> A; (A, Acc) -> Acc ++ Sep ++ A From 677d8b1a2972c3c4134aaf07780f2b16846e14be Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 21 Feb 2011 22:33:23 +0100 Subject: [PATCH 05/47] Add support for '@online@' Shared Roster Group (thanks to Martin Langhoff)(EJAB-1391) New version of the @online@ patch originally by Collabora. Notes: - the presence push is mediated via the group rather than per user - this may reduce memory footprint... _if_ ejabberd has some smart optimisation in that codepath - it assumes that any group with membership @online@ _displays_ online as well -- this is a simplification and breaks the decoupling that ejabberd has in this regard. --- doc/guide.tex | 10 ++-- src/mod_shared_roster.erl | 113 +++++++++++++++++++++++++++++++++++--- 2 files changed, 111 insertions(+), 12 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index e0bb42e4c..2bacd57c9 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -4055,11 +4055,13 @@ has a unique identification and the following parameters: \item[Name] The name of the group, which will be displayed in the roster. \item[Description] The description of the group. This parameter does not affect anything. -\item[Members] A list of full JIDs of group members, entered one per line in +\item[Members] A list of JIDs of group members, entered one per line in the Web Admin. - To put as members all the registered users in the virtual hosts, - you can use the special directive: @all@. - Note that this directive is designed for a small server with just a few hundred users. + The special member directive \term{@all@} + represents all the registered users in the virtual host; + which is only recommended for a small server with just a few hundred users. + The special member directive \term{@online@} + represents the online users in the virtual host. \item[Displayed groups] A list of groups that will be in the rosters of this group's members. \end{description} diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 13348cffb..14879cce0 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -37,6 +37,8 @@ process_item/2, in_subscription/6, out_subscription/4, + user_available/1, + unset_presence/4, register_user/2, remove_user/2, list_groups/1, @@ -85,6 +87,10 @@ start(Host, _Opts) -> ?MODULE, get_jid_info, 70), ejabberd_hooks:add(roster_process_item, Host, ?MODULE, process_item, 50), + ejabberd_hooks:add(user_available_hook, Host, + ?MODULE, user_available, 50), + ejabberd_hooks:add(unset_presence_hook, Host, + ?MODULE, unset_presence, 50), ejabberd_hooks:add(register_user, Host, ?MODULE, register_user, 50), ejabberd_hooks:add(remove_user, Host, @@ -109,6 +115,10 @@ stop(Host) -> ?MODULE, get_jid_info, 70), ejabberd_hooks:delete(roster_process_item, Host, ?MODULE, process_item, 50), + ejabberd_hooks:delete(user_available_hook, Host, + ?MODULE, user_available, 50), + ejabberd_hooks:delete(unset_presence_hook, Host, + ?MODULE, unset_presence, 50), ejabberd_hooks:delete(register_user, Host, ?MODULE, register_user, 50), ejabberd_hooks:delete(remove_user, Host, @@ -470,21 +480,38 @@ get_group_opt(Host, Group, Opt, Default) -> Default end. +get_online_users(Host) -> + lists:usort([{U, S} || {U, S, _} <- ejabberd_sm:get_vh_session_list(Host)]). + get_group_users(Host, Group) -> case get_group_opt(Host, Group, all_users, false) of true -> ejabberd_auth:get_vh_registered_users(Host); false -> [] - end ++ get_group_explicit_users(Host, Group). + end ++ + case get_group_opt(Host, Group, online_users, false) of + true -> + get_online_users(Host); + false -> + [] + end ++ + get_group_explicit_users(Host, Group). -get_group_users(_User, Host, Group, GroupOpts) -> +get_group_users(Host, Group, GroupOpts) -> case proplists:get_value(all_users, GroupOpts, false) of true -> ejabberd_auth:get_vh_registered_users(Host); false -> [] - end ++ get_group_explicit_users(Host, Group). + end ++ + case proplists:get_value(online_users, GroupOpts, false) of + true -> + get_online_users(Host); + false -> + [] + end ++ + get_group_explicit_users(Host, Group). %% @spec (Host::string(), Group::string()) -> [{User::string(), Server::string()}] get_group_explicit_users(Host, Group) -> @@ -502,11 +529,20 @@ get_group_explicit_users(Host, Group) -> get_group_name(Host, Group) -> get_group_opt(Host, Group, name, Group). -%% Get list of names of groups that have @all@ in the memberlist +%% Get list of names of groups that have @all@/@online@/etc in the memberlist get_special_users_groups(Host) -> lists:filter( fun(Group) -> get_group_opt(Host, Group, all_users, false) + orelse get_group_opt(Host, Group, online_users, false) + end, + list_groups(Host)). + +%% Get list of names of groups that have @online@ in the memberlist +get_special_users_groups_online(Host) -> + lists:filter( + fun(Group) -> + get_group_opt(Host, Group, online_users, false) end, list_groups(Host)). @@ -661,7 +697,7 @@ push_user_to_members(User, Server, Subscription) -> lists:foreach( fun({U, S}) -> push_roster_item(U, S, LUser, LServer, GroupName, Subscription) - end, get_group_users(LUser, LServer, Group, GroupOpts)) + end, get_group_users(LServer, Group, GroupOpts)) end, lists:usort(SpecialGroups++UserGroups)). push_user_to_displayed(LUser, LServer, Group, Subscription) -> @@ -673,7 +709,8 @@ push_user_to_displayed(LUser, LServer, Group, Subscription) -> push_user_to_group(LUser, LServer, Group, GroupName, Subscription) -> lists:foreach( - fun({U, S}) -> + fun({U, S}) when (U == LUser) and (S == LServer) -> ok; + ({U, S}) -> push_roster_item(U, S, LUser, LServer, GroupName, Subscription) end, get_group_users(LServer, Group)). @@ -757,6 +794,51 @@ ask_to_pending(subscribe) -> out; ask_to_pending(unsubscribe) -> none; ask_to_pending(Ask) -> Ask. +user_available(New) -> + LUser = New#jid.luser, + LServer = New#jid.lserver, + Resources = ejabberd_sm:get_user_resources(LUser, LServer), + ?DEBUG("user_available for ~p @ ~p (~p resources)", + [LUser, LServer, length(Resources)]), + case length(Resources) of + %% first session for this user + 1 -> + %% This is a simplification - we ignore he 'display' + %% property - @online@ is always reflective. + OnlineGroups = get_special_users_groups_online(LServer), + lists:foreach( + fun(OG) -> + ?DEBUG("user_available: pushing ~p @ ~p grp ~p", + [LUser, LServer, OG ]), + push_user_to_displayed(LUser, LServer, OG, both) + end, OnlineGroups); + _ -> + ok + end. + +unset_presence(LUser, LServer, Resource, Status) -> + Resources = ejabberd_sm:get_user_resources(LUser, LServer), + ?DEBUG("unset_presence for ~p @ ~p / ~p -> ~p (~p resources)", + [LUser, LServer, Resource, Status, length(Resources)]), + %% if user has no resources left... + case length(Resources) of + 0 -> + %% This is a simplification - we ignore he 'display' + %% property - @online@ is always reflective. + OnlineGroups = get_special_users_groups_online(LServer), + %% for each of these groups... + lists:foreach( + fun(OG) -> + %% Push removal of the old user to members of groups + %% where the group that this uwas members was displayed + push_user_to_displayed(LUser, LServer, OG, remove), + %% Push removal of members of groups that where + %% displayed to the group which thiuser has left + push_displayed_to_user(LUser, LServer, OG, LServer,remove) + end, OnlineGroups); + _ -> + ok + end. %%--------------------- %% Web Admin @@ -860,6 +942,7 @@ shared_roster_group(Host, Group, Query, Lang) -> Name = get_opt(GroupOpts, name, ""), Description = get_opt(GroupOpts, description, ""), AllUsers = get_opt(GroupOpts, all_users, false), + OnlineUsers = get_opt(GroupOpts, online_users, false), %%Disabled = false, DisplayedGroups = get_opt(GroupOpts, displayed_groups, []), Members = mod_shared_roster:get_group_explicit_users(Host, Group), @@ -869,7 +952,14 @@ shared_roster_group(Host, Group, Query, Lang) -> "@all@\n"; true -> [] - end ++ [[us_to_list(Member), $\n] || Member <- Members], + end ++ + if + OnlineUsers -> + "@online@\n"; + true -> + [] + end ++ + [[us_to_list(Member), $\n] || Member <- Members], FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups], DescNL = length(element(2, regexp:split(Description, "\n"))), FGroup = @@ -953,6 +1043,8 @@ shared_roster_group_parse_query(Host, Group, Query) -> case SJID of "@all@" -> USs; + "@online@" -> + USs; _ -> case jlib:string_to_jid(SJID) of JID when is_record(JID, jid) -> @@ -967,10 +1059,15 @@ shared_roster_group_parse_query(Host, Group, Query) -> true -> [{all_users, true}]; false -> [] end, + OnlineUsersOpt = + case lists:member("@online@", SJIDs) of + true -> [{online_users, true}]; + false -> [] + end, mod_shared_roster:set_group_opts( Host, Group, - NameOpt ++ DispGroupsOpt ++ DescriptionOpt ++ AllUsersOpt), + NameOpt ++ DispGroupsOpt ++ DescriptionOpt ++ AllUsersOpt ++ OnlineUsersOpt), if NewMembers == error -> error; From db0962804dd9af59acea1b1fa1ce32df54c87aeb Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 22 Feb 2011 23:43:38 +0100 Subject: [PATCH 06/47] Tweak pg2_backport.erl to work with Erlang older than R13A (EJAB-1349) --- src/pg2_backport.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pg2_backport.erl b/src/pg2_backport.erl index 353bef0eb..faa775524 100644 --- a/src/pg2_backport.erl +++ b/src/pg2_backport.erl @@ -207,9 +207,12 @@ terminate(_Reason, _S) -> store(List) -> _ = [(assure_group(Name) andalso - [join_group(Name, P) || P <- Members -- group_members(Name)]) || + store2(Name, Members)) || [Name, Members] <- List], ok. +store2(Name, Members) -> + [join_group(Name, P) || P <- Members -- group_members(Name)], + true. assure_group(Name) -> Key = {group, Name}, From 339fa6e41bc4e0756c1f27b83bd7685c429c595a Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 28 Feb 2011 18:40:45 +0100 Subject: [PATCH 07/47] ejabberdctl needs space between INET_DIST_INTERFACE (thanks to Dale Chase)(EJAB-1416) --- src/ejabberdctl.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberdctl.template b/src/ejabberdctl.template index f12a12482..04e0e6f27 100644 --- a/src/ejabberdctl.template +++ b/src/ejabberdctl.template @@ -83,7 +83,7 @@ else fi if [ "$INET_DIST_INTERFACE" != "" ] ; then - KERNEL_OPTS+="-kernel inet_dist_use_interface \"${INET_DIST_INTERFACE}\"" + KERNEL_OPTS+=" -kernel inet_dist_use_interface \"${INET_DIST_INTERFACE}\"" fi ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" From 1548a18b5eca70123d1449d9d63cd5e54c683b8b Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 1 Mar 2011 22:32:50 +0100 Subject: [PATCH 08/47] mod_irc must send presence unavailable to the departing occupant (EJAB-1417) --- src/mod_irc/mod_irc_connection.erl | 35 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/mod_irc/mod_irc_connection.erl b/src/mod_irc/mod_irc_connection.erl index 55432dd1c..c342f2877 100644 --- a/src/mod_irc/mod_irc_connection.erl +++ b/src/mod_irc/mod_irc_connection.erl @@ -219,6 +219,7 @@ handle_info({route_chan, Channel, Resource, NewStateData = case xml:get_attr_s("type", Attrs) of "unavailable" -> + send_stanza_unavailable(Channel, StateData), S1 = ?SEND(io_lib:format("PART #~s\r\n", [Channel])), S1#state{channels = dict:erase(Channel, S1#state.channels)}; @@ -656,13 +657,9 @@ terminate(_Reason, _StateName, FullStateData) -> bounce_messages("Server Connect Failed"), lists:foreach( fun(Chan) -> - ejabberd_router:route( - jlib:make_jid( - lists:concat([Chan, "%", StateData#state.server]), - StateData#state.host, StateData#state.nick), - StateData#state.user, - {xmlelement, "presence", [{"type", "error"}], - [Error]}) + Stanza = {xmlelement, "presence", [{"type", "error"}], + [Error]}, + send_stanza(Chan, StateData, Stanza) end, dict:fetch_keys(StateData#state.channels)), case StateData#state.socket of undefined -> @@ -672,6 +669,30 @@ terminate(_Reason, _StateName, FullStateData) -> end, ok. +send_stanza(Chan, StateData, Stanza) -> + ejabberd_router:route( + jlib:make_jid( + lists:concat([Chan, "%", StateData#state.server]), + StateData#state.host, StateData#state.nick), + StateData#state.user, + Stanza). + +send_stanza_unavailable(Chan, StateData) -> + Affiliation = "member", % this is a simplification + Role = "none", + Stanza = + {xmlelement, "presence", [{"type", "unavailable"}], + [{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], + [{xmlelement, "item", + [{"affiliation", Affiliation}, + {"role", Role}], + []}, + {xmlelement, "status", + [{"code", "110"}], + []} + ]}]}, + send_stanza(Chan, StateData, Stanza). + %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- From e0d14c3b8d84f5249e388844f7901fed88b18209 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 3 Mar 2011 00:02:28 +0100 Subject: [PATCH 09/47] captcha_host must have the port number to get protocol (EJAB-1418) --- doc/guide.tex | 10 +++++----- src/ejabberd.cfg.example | 2 +- src/ejabberd_captcha.erl | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index 2bacd57c9..c51baca90 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -1633,11 +1633,11 @@ The configurable options are: \titem{\{captcha\_cmd, Path\}} Full path to a script that generates the image. The default value is an empty string: \term{""} - \titem{\{captcha\_host, Host\}} - Host part of the URL sent to the user. - You can include the port number. - The URL sent to the user is formed by: \term{http://Host/captcha/} - The default value is the first hostname configured. + \titem{\{captcha\_host, HostPort\}} + Host part of the URL sent to the user, + and the port number where ejabberd listens for CAPTCHA requests. + The URL sent to the user is formed by: \term{http://Host:Port/captcha/} + The default value is: the first hostname configured, and port 5280. \end{description} Additionally, an \term{ejabberd\_http} listener must be enabled with the \term{captcha} option. diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example index 52ffc6825..0912bf559 100644 --- a/src/ejabberd.cfg.example +++ b/src/ejabberd.cfg.example @@ -475,7 +475,7 @@ %%{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}. %% -%% Host part of the URL sent to the user. +%% Host for the URL and port where ejabberd listens for CAPTCHA requests. %% %%{captcha_host, "example.org:5280"}. diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 455ffad9d..0f3aee76c 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -406,12 +406,12 @@ get_prog_name() -> get_url(Str) -> CaptchaHost = ejabberd_config:get_local_option(captcha_host), - TransferProt = atom_to_list(get_transfer_protocol(CaptchaHost)), case CaptchaHost of Host when is_list(Host) -> + TransferProt = atom_to_list(get_transfer_protocol(CaptchaHost)), TransferProt ++ "://" ++ Host ++ "/captcha/" ++ Str; _ -> - TransferProt ++ "://" ++ ?MYNAME ++ "/captcha/" ++ Str + "http://" ++ ?MYNAME ++ ":5280/captcha/" ++ Str end. get_transfer_protocol(CaptchaHost) -> From a1f20a5bc0729095feef96b3d021df169392e580 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 3 Mar 2011 11:35:47 +0100 Subject: [PATCH 10/47] If the port number isn't listener, then specify the protocol (EJAB-1418) --- doc/guide.tex | 6 +++++- src/ejabberd_captcha.erl | 21 ++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index c51baca90..72bb13247 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -1633,11 +1633,14 @@ The configurable options are: \titem{\{captcha\_cmd, Path\}} Full path to a script that generates the image. The default value is an empty string: \term{""} - \titem{\{captcha\_host, HostPort\}} + \titem{\{captcha\_host, ProtocolHostPort\}} Host part of the URL sent to the user, and the port number where ejabberd listens for CAPTCHA requests. The URL sent to the user is formed by: \term{http://Host:Port/captcha/} The default value is: the first hostname configured, and port 5280. + If the port number you specify does not match exactly an ejabberd listener + (because you are using a reverse proxy or other port-forwarding tool), + then specify also the transfer protocol, as seen in the example below. \end{description} Additionally, an \term{ejabberd\_http} listener must be enabled with the \term{captcha} option. @@ -1649,6 +1652,7 @@ Example configuration: {captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}. {captcha_host, "example.org:5280"}. +%% {captcha_host, "https://example.org:443"}. {listen, [ diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 0f3aee76c..797a6152d 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -406,23 +406,21 @@ get_prog_name() -> get_url(Str) -> CaptchaHost = ejabberd_config:get_local_option(captcha_host), - case CaptchaHost of - Host when is_list(Host) -> - TransferProt = atom_to_list(get_transfer_protocol(CaptchaHost)), - TransferProt ++ "://" ++ Host ++ "/captcha/" ++ Str; + case string:tokens(CaptchaHost, ":") of + [TransferProt, Host, PortString] -> + TransferProt ++ ":" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str; + [Host, PortString] -> + TransferProt = atom_to_list(get_transfer_protocol(PortString)), + TransferProt ++ "://" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str; _ -> "http://" ++ ?MYNAME ++ ":5280/captcha/" ++ Str end. -get_transfer_protocol(CaptchaHost) -> - PortNumber = get_port_number_from_captcha_host_option(CaptchaHost), +get_transfer_protocol(PortString) -> + PortNumber = list_to_integer(PortString), PortListeners = get_port_listeners(PortNumber), get_captcha_transfer_protocol(PortListeners). -get_port_number_from_captcha_host_option(CaptchaHost) -> - [_Host, PortString] = string:tokens(CaptchaHost, ":"), - list_to_integer(PortString). - get_port_listeners(PortNumber) -> AllListeners = ejabberd_config:get_local_option(listen), lists:filter( @@ -435,7 +433,8 @@ get_port_listeners(PortNumber) -> get_captcha_transfer_protocol([]) -> throw("The port number mentioned in captcha_host is not " - "a ejabberd_http listener with 'captcha' option."); + "a ejabberd_http listener with 'captcha' option. " + "Change the port number or specify http:// in that option."); get_captcha_transfer_protocol([{{_Port, _Ip, tcp}, ejabberd_http, Opts} | Listeners]) -> case lists:member(captcha, Opts) of From b116957982f78ed90f71fb4bfab9b63f97b9eeef Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 9 Mar 2011 16:25:05 +0100 Subject: [PATCH 11/47] Fix bashism and make some lines similar to master branch (EJAB-1404) --- src/ejabberdctl.template | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ejabberdctl.template b/src/ejabberdctl.template index 04e0e6f27..650aa520d 100644 --- a/src/ejabberdctl.template +++ b/src/ejabberdctl.template @@ -76,14 +76,12 @@ fi NAME=-name [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && NAME=-sname -if [ "$FIREWALL_WINDOW" = "" ] ; then - KERNEL_OPTS="" -else - KERNEL_OPTS="-kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" +KERNEL_OPTS="" +if [ "$FIREWALL_WINDOW" != "" ] ; then + KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" fi - if [ "$INET_DIST_INTERFACE" != "" ] ; then - KERNEL_OPTS+=" -kernel inet_dist_use_interface \"${INET_DIST_INTERFACE}\"" + KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_use_interface \"${INET_DIST_INTERFACE}\"" fi ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" From 18fd67b31129272266c4a28fdb21cb78e792950e Mon Sep 17 00:00:00 2001 From: Badlop Date: Sun, 13 Mar 2011 18:08:29 +0100 Subject: [PATCH 12/47] Change string in WebAdmin to reuse an existing one --- src/web/ejabberd_web_admin.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl index 607bdcbfe..90e301401 100644 --- a/src/web/ejabberd_web_admin.erl +++ b/src/web/ejabberd_web_admin.erl @@ -1028,7 +1028,7 @@ process_admin(global, auth = {_, _Auth, AJID}, lang = Lang}) -> Res = list_vhosts(Lang, AJID), - make_xhtml(?H1GL(?T("ejabberd virtual hosts"), "virtualhost", "Virtual Hosting") ++ Res, global, Lang, AJID); + make_xhtml(?H1GL(?T("Virtual Hosts"), "virtualhost", "Virtual Hosting") ++ Res, global, Lang, AJID); process_admin(Host, #request{path = ["users"], From abcbcd1f2cdb4617c4c0768f6c93d82bf0e61b5d Mon Sep 17 00:00:00 2001 From: Badlop Date: Sun, 13 Mar 2011 18:33:32 +0100 Subject: [PATCH 13/47] Update the changed string in the PO translation files --- src/msgs/ca.msg | 2 +- src/msgs/ca.po | 4 ++-- src/msgs/cs.msg | 2 +- src/msgs/cs.po | 4 ++-- src/msgs/de.msg | 2 +- src/msgs/de.po | 4 ++-- src/msgs/ejabberd.pot | 2 +- src/msgs/el.msg | 2 +- src/msgs/el.po | 4 ++-- src/msgs/eo.msg | 2 +- src/msgs/eo.po | 7 ++----- src/msgs/es.msg | 2 +- src/msgs/es.po | 6 +++--- src/msgs/fr.msg | 2 +- src/msgs/fr.po | 7 ++----- src/msgs/gl.msg | 2 +- src/msgs/gl.po | 7 ++----- src/msgs/id.msg | 2 +- src/msgs/id.po | 4 ++-- src/msgs/it.msg | 2 +- src/msgs/it.po | 4 ++-- src/msgs/ja.msg | 2 +- src/msgs/ja.po | 7 ++----- src/msgs/nl.msg | 2 +- src/msgs/nl.po | 2 +- src/msgs/no.msg | 2 +- src/msgs/no.po | 4 ++-- src/msgs/pl.msg | 2 +- src/msgs/pl.po | 4 ++-- src/msgs/pt-br.msg | 2 +- src/msgs/pt-br.po | 4 ++-- src/msgs/pt.po | 4 ++-- src/msgs/ru.msg | 2 +- src/msgs/ru.po | 4 ++-- src/msgs/sk.msg | 2 +- src/msgs/sk.po | 7 ++----- src/msgs/sv.msg | 2 +- src/msgs/sv.po | 4 ++-- src/msgs/th.msg | 2 +- src/msgs/th.po | 7 ++----- src/msgs/tr.msg | 2 +- src/msgs/tr.po | 4 ++-- src/msgs/uk.msg | 2 +- src/msgs/uk.po | 4 ++-- src/msgs/vi.msg | 2 +- src/msgs/vi.po | 7 ++----- src/msgs/wa.msg | 2 +- src/msgs/wa.po | 7 ++----- src/msgs/zh.msg | 2 +- src/msgs/zh.po | 7 ++----- 50 files changed, 75 insertions(+), 102 deletions(-) diff --git a/src/msgs/ca.msg b/src/msgs/ca.msg index 56a737c18..2742289a8 100644 --- a/src/msgs/ca.msg +++ b/src/msgs/ca.msg @@ -77,7 +77,6 @@ {"ejabberd Publish-Subscribe module","Mòdul ejannerd Publicar-Subscriure"}. {"ejabberd SOCKS5 Bytestreams module","mòdul ejabberd SOCKS5 Bytestreams"}. {"ejabberd vCard module","Mòdul ejabberd vCard"}. -{"ejabberd virtual hosts","Hosts virtuals del ejabberd"}. {"ejabberd Web Admin","Web d'administració del ejabberd"}. {"Elements","Elements"}. {"Email","Email"}. @@ -362,6 +361,7 @@ {"User","Usuari"}. {"Validate","Validar"}. {"vCard User Search","Recerca de vCard d'usuari"}. +{"Virtual Hosts","Hosts virtuals"}. {"Visitors are not allowed to change their nicknames in this room","Els visitants no tenen permés canviar el seus Nicknames en esta sala"}. {"Visitors are not allowed to send messages to all occupants","Els visitants no poden enviar missatges a tots els ocupants"}. {"Wednesday","Dimecres"}. diff --git a/src/msgs/ca.po b/src/msgs/ca.po index c916641c1..4554e91cc 100644 --- a/src/msgs/ca.po +++ b/src/msgs/ca.po @@ -1365,8 +1365,8 @@ msgid "~s access rule configuration" msgstr "Configuració de les Regles d'Accés ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Hosts virtuals del ejabberd" +msgid "Virtual Hosts" +msgstr "Hosts virtuals" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/cs.msg b/src/msgs/cs.msg index 21d04c334..eed1c47d5 100644 --- a/src/msgs/cs.msg +++ b/src/msgs/cs.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modul"}. {"ejabberd vCard module","ejabberd vCard modul"}. -{"ejabberd virtual hosts","Virtuální hostitelé ejabberd"}. {"ejabberd Web Admin","Webová administrace ejabberd"}. {"Elements","Položek"}. {"Email","E-mail"}. @@ -388,6 +387,7 @@ {"User","Uživatel"}. {"Validate","Ověřit"}. {"vCard User Search","Hledání uživatelů podle vizitek"}. +{"Virtual Hosts","Virtuální hostitelé"}. {"Visitors are not allowed to change their nicknames in this room","Návštěvníkům této místnosti je zakázáno měnit přezdívku"}. {"Visitors are not allowed to send messages to all occupants","Návštevníci nemají povoleno zasílat zprávy všem účastníkům konference"}. {"Wednesday","Středa"}. diff --git a/src/msgs/cs.po b/src/msgs/cs.po index fd3bd337f..c3f02cbf5 100644 --- a/src/msgs/cs.po +++ b/src/msgs/cs.po @@ -1345,8 +1345,8 @@ msgid "~s access rule configuration" msgstr "~s konfigurace pravidla přístupu" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Virtuální hostitelé ejabberd" +msgid "Virtual Hosts" +msgstr "Virtuální hostitelé" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/de.msg b/src/msgs/de.msg index 224b5241d..6dde04f8c 100644 --- a/src/msgs/de.msg +++ b/src/msgs/de.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe-Modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5-Bytestreams-Modul"}. {"ejabberd vCard module","ejabberd vCard-Modul"}. -{"ejabberd virtual hosts","ejabberd virtuelle Hosts"}. {"ejabberd Web Admin","ejabberd Web-Admin"}. {"Elements","Elemente"}. {"Email","E-Mail"}. @@ -388,6 +387,7 @@ {"Users Last Activity","Letzte Benutzeraktivität"}. {"Validate","Validieren"}. {"vCard User Search","vCard-Benutzer-Suche"}. +{"Virtual Hosts","Virtuelle Hosts"}. {"Visitors are not allowed to change their nicknames in this room","Besucher dürfen in diesem Raum ihren Benutzernamen nicht ändern"}. {"Visitors are not allowed to send messages to all occupants","Besucher dürfen nicht an alle Teilnehmer Nachrichten verschicken"}. {"Wednesday","Mittwoch"}. diff --git a/src/msgs/de.po b/src/msgs/de.po index 90abdd6ea..baec05323 100644 --- a/src/msgs/de.po +++ b/src/msgs/de.po @@ -1378,8 +1378,8 @@ msgid "~s access rule configuration" msgstr "~s Zugangsregel-Konfiguration" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "ejabberd virtuelle Hosts" +msgid "Virtual Hosts" +msgstr "Virtuelle Hosts" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/ejabberd.pot b/src/msgs/ejabberd.pot index 3311d6b71..921a307fe 100644 --- a/src/msgs/ejabberd.pot +++ b/src/msgs/ejabberd.pot @@ -1329,7 +1329,7 @@ msgid "~s access rule configuration" msgstr "" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" +msgid "Virtual Hosts" msgstr "" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 diff --git a/src/msgs/el.msg b/src/msgs/el.msg index d0b68fc7e..4fa37a046 100644 --- a/src/msgs/el.msg +++ b/src/msgs/el.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","ejabberd module Δημοσίευσης-Εγγραφής"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","ejabberd vCard module"}. -{"ejabberd virtual hosts","εικονικοί κεντρικοί υπολογιστές ejabberd"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Στοιχεία"}. {"Email","Email"}. @@ -388,6 +387,7 @@ {"User","Χρήστης"}. {"Validate","Επαληθεύστε"}. {"vCard User Search","vCard Αναζήτηση χρηστών"}. +{"Virtual Hosts","εικονικοί κεντρικοί υπολογιστές"}. {"Visitors are not allowed to change their nicknames in this room","Οι επισκέπτες δεν επιτρέπεται να αλλάξουν τα ψευδώνυμα τους σε αυτή την αίθουσα"}. {"Visitors are not allowed to send messages to all occupants","Οι επισκέπτες δεν επιτρέπεται να στείλουν μηνύματα σε όλους τους συμμετέχωντες"}. {"Wednesday","Τετάρτη"}. diff --git a/src/msgs/el.po b/src/msgs/el.po index 35a74ac30..68561de5a 100644 --- a/src/msgs/el.po +++ b/src/msgs/el.po @@ -1382,8 +1382,8 @@ msgid "~s access rule configuration" msgstr "~s διαμόρφωση κανόνα πρόσβασης" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "εικονικοί κεντρικοί υπολογιστές ejabberd" +msgid "Virtual Hosts" +msgstr "εικονικοί κεντρικοί υπολογιστές" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/eo.msg b/src/msgs/eo.msg index 5fd21c37c..435f44d4f 100644 --- a/src/msgs/eo.msg +++ b/src/msgs/eo.msg @@ -77,7 +77,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Public-Abonada modulo"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bajtfluo modulo"}. {"ejabberd vCard module","ejabberd vCard-modulo"}. -{"ejabberd virtual hosts","ejabberd virtual-gastigoj"}. {"ejabberd Web Admin","ejabberd Teksaĵa Administro"}. {"Elements","Eroj"}. {"Email","Retpoŝto"}. @@ -362,6 +361,7 @@ {"User","Uzanto"}. {"Validate","Validigu"}. {"vCard User Search","Serĉado de vizitkartoj"}. +{"Virtual Hosts","Virtual-gastigoj"}. {"Visitors are not allowed to change their nicknames in this room","Ne estas permesata al vizitantoj ŝanĝi siajn kaŝnomojn en ĉi tiu ĉambro"}. {"Visitors are not allowed to send messages to all occupants","Vizitantoj ne rajtas sendi mesaĝojn al ĉiuj partoprenantoj"}. {"Wednesday","Merkredo"}. diff --git a/src/msgs/eo.po b/src/msgs/eo.po index 9d84ba3eb..62b93a76f 100644 --- a/src/msgs/eo.po +++ b/src/msgs/eo.po @@ -1359,8 +1359,8 @@ msgid "~s access rule configuration" msgstr "Agordo de atingo-reguloj de ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "ejabberd virtual-gastigoj" +msgid "Virtual Hosts" +msgstr "Virtual-gastigoj" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1789,9 +1789,6 @@ msgstr "" #~ msgid "(Raw)" #~ msgstr "(Kruda)" -#~ msgid "Virtual Hosts" -#~ msgstr "Virtual-gastigoj" - #~ msgid "Specified nickname is already registered" #~ msgstr "Donita kaŝnomo jam estas registrita" diff --git a/src/msgs/es.msg b/src/msgs/es.msg index 3b5a7a761..17598c45a 100644 --- a/src/msgs/es.msg +++ b/src/msgs/es.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","Módulo de Publicar-Subscribir de ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Módulo SOCKS5 Bytestreams para ejabberd"}. {"ejabberd vCard module","Módulo vCard para ejabberd"}. -{"ejabberd virtual hosts","Dominios de ejabberd"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Elementos"}. {"Email","correo"}. @@ -388,6 +387,7 @@ {"User","Usuario"}. {"Validate","Validar"}. {"vCard User Search","Buscar vCard de usuario"}. +{"Virtual Hosts","Dominios Virtuales"}. {"Visitors are not allowed to change their nicknames in this room","Los visitantes no tienen permitido cambiar sus apodos en esta sala"}. {"Visitors are not allowed to send messages to all occupants","Los visitantes no pueden enviar mensajes a todos los ocupantes"}. {"Wednesday","miércoles"}. diff --git a/src/msgs/es.po b/src/msgs/es.po index fffef21f2..0d791b811 100644 --- a/src/msgs/es.po +++ b/src/msgs/es.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: es\n" "PO-Revision-Date: 2010-11-19 13:40+0100\n" -"Last-Translator: \n" +"Last-Translator: Badlop \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1367,8 +1367,8 @@ msgid "~s access rule configuration" msgstr "Configuración de las Regla de Acceso ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Dominios de ejabberd" +msgid "Virtual Hosts" +msgstr "Dominios Virtuales" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/fr.msg b/src/msgs/fr.msg index 724582ec1..ee9ec2a38 100644 --- a/src/msgs/fr.msg +++ b/src/msgs/fr.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","Module Publish-Subscribe d'ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","Module vCard ejabberd"}. -{"ejabberd virtual hosts","Serveurs virtuels d'ejabberd"}. {"ejabberd Web Admin","Console Web d'administration de ejabberd"}. {"Elements","Éléments"}. {"Email","Email"}. @@ -388,6 +387,7 @@ {"User","Utilisateur"}. {"Validate","Valider"}. {"vCard User Search","Recherche dans l'annnuaire"}. +{"Virtual Hosts","Serveurs virtuels"}. {"Visitors are not allowed to change their nicknames in this room","Les visiteurs ne sont pas autorisés à changer de pseudo dans ce salon"}. {"Visitors are not allowed to send messages to all occupants","Les visiteurs ne sont pas autorisés à envoyer des messages à tout les occupants"}. {"Wednesday","Mercredi"}. diff --git a/src/msgs/fr.po b/src/msgs/fr.po index 8ee35396e..7a807d877 100644 --- a/src/msgs/fr.po +++ b/src/msgs/fr.po @@ -1381,8 +1381,8 @@ msgid "~s access rule configuration" msgstr "Configuration des règles d'accès ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Serveurs virtuels d'ejabberd" +msgid "Virtual Hosts" +msgstr "Serveurs virtuels" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1824,6 +1824,3 @@ msgstr "Effacer" #~ msgid "(Raw)" #~ msgstr "(Brut)" - -#~ msgid "Virtual Hosts" -#~ msgstr "Serveurs virtuels" diff --git a/src/msgs/gl.msg b/src/msgs/gl.msg index d6db76590..219bea35d 100644 --- a/src/msgs/gl.msg +++ b/src/msgs/gl.msg @@ -73,7 +73,6 @@ {"ejabberd Publish-Subscribe module","Módulo de Publicar-Subscribir de ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","Módulo vCard para ejabberd"}. -{"ejabberd virtual hosts","Hosts virtuais de ejabberd"}. {"ejabberd Web Admin","Ejabberd Administrador Web"}. {"Elements","Elementos"}. {"Email","Email"}. @@ -356,6 +355,7 @@ {"User","Usuario"}. {"Validate","Validar"}. {"vCard User Search","Procura de usuario en vCard"}. +{"Virtual Hosts","Hosts Virtuais"}. {"Visitors are not allowed to change their nicknames in this room","Os visitantes non están autorizados a cambiar os seus That alcumes nesta sala"}. {"Visitors are not allowed to send messages to all occupants","Os visitantes non poden enviar mensaxes a todos os ocupantes"}. {"Wednesday","Mércores"}. diff --git a/src/msgs/gl.po b/src/msgs/gl.po index 3fe3b09e9..0e0036831 100644 --- a/src/msgs/gl.po +++ b/src/msgs/gl.po @@ -1370,8 +1370,8 @@ msgid "~s access rule configuration" msgstr "Configuración das Regra de Acceso ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Hosts virtuais de ejabberd" +msgid "Virtual Hosts" +msgstr "Hosts Virtuais" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1805,9 +1805,6 @@ msgstr "" #~ msgid "(Raw)" #~ msgstr "(Cru)" -#~ msgid "Virtual Hosts" -#~ msgstr "Hosts Virtuais" - #~ msgid "Specified nickname is already registered" #~ msgstr "O alcume especificado xa está rexistrado, terás que buscar outro" diff --git a/src/msgs/id.msg b/src/msgs/id.msg index d843e1ed6..1922ad0c7 100644 --- a/src/msgs/id.msg +++ b/src/msgs/id.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","Modul ejabberd Setujui-Pertemanan"}. {"ejabberd SOCKS5 Bytestreams module","modul ejabberd SOCKS5 Bytestreams"}. {"ejabberd vCard module","Modul ejabberd vCard"}. -{"ejabberd virtual hosts","ejabberd virtual hosts"}. {"ejabberd Web Admin","Admin Web ejabberd"}. {"Elements","Elemen-elemen"}. {"Email","Email"}. @@ -388,6 +387,7 @@ {"Users","Pengguna"}. {"Validate","Mengesahkan"}. {"vCard User Search","vCard Pencarian Pengguna"}. +{"Virtual Hosts","Virtual Hosts"}. {"Visitors are not allowed to change their nicknames in this room","Visitor tidak diperbolehkan untuk mengubah nama julukan di ruangan ini"}. {"Visitors are not allowed to send messages to all occupants","Visitor tidak diperbolehkan untuk mengirim pesan ke semua penghuni"}. {"Wednesday","Rabu"}. diff --git a/src/msgs/id.po b/src/msgs/id.po index 4dca85ad1..e71c74836 100644 --- a/src/msgs/id.po +++ b/src/msgs/id.po @@ -1362,8 +1362,8 @@ msgid "~s access rule configuration" msgstr "~s aturan akses konfigurasi" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "ejabberd virtual hosts" +msgid "Virtual Hosts" +msgstr "Virtual Hosts" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/it.msg b/src/msgs/it.msg index 329450a54..712745abf 100644 --- a/src/msgs/it.msg +++ b/src/msgs/it.msg @@ -77,7 +77,6 @@ {"ejabberd Publish-Subscribe module","Modulo Pubblicazione/Iscrizione (PubSub) per ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Modulo SOCKS5 Bytestreams per ejabberd"}. {"ejabberd vCard module","Modulo vCard per ejabberd"}. -{"ejabberd virtual hosts","Host virtuali di ejabberd"}. {"ejabberd Web Admin","Amministrazione web ejabberd"}. {"Elements","Elementi"}. {"Email","E-mail"}. @@ -362,6 +361,7 @@ {"User","Utente"}. {"Validate","Validare"}. {"vCard User Search","Ricerca di utenti per vCard"}. +{"Virtual Hosts","Host Virtuali"}. {"Visitors are not allowed to change their nicknames in this room","Non è consentito ai visitatori cambiare il nickname in questa stanza"}. {"Visitors are not allowed to send messages to all occupants","Non è consentito ai visitatori l'invio di messaggi a tutti i presenti"}. {"Wednesday","Mercoledì"}. diff --git a/src/msgs/it.po b/src/msgs/it.po index 3dc6ddd24..b049385d6 100644 --- a/src/msgs/it.po +++ b/src/msgs/it.po @@ -1372,8 +1372,8 @@ msgid "~s access rule configuration" msgstr "Configurazione delle regole di accesso per ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Host virtuali di ejabberd" +msgid "Virtual Hosts" +msgstr "Host Virtuali" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/ja.msg b/src/msgs/ja.msg index c5b5af3bd..8da952c61 100644 --- a/src/msgs/ja.msg +++ b/src/msgs/ja.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","ejabberd vCard module"}. -{"ejabberd virtual hosts","ejabberd ヴァーチャルホスト"}. {"ejabberd Web Admin","ejabberd Web 管理"}. {"Elements","要素"}. {"Email","メールアドレス"}. @@ -388,6 +387,7 @@ {"Users Last Activity","ユーザーの活動履歴"}. {"Validate","検証"}. {"vCard User Search","vCard ユーザー検索"}. +{"Virtual Hosts","ヴァーチャルホスト"}. {"Visitors are not allowed to change their nicknames in this room","ビジターはこのチャットルームでニックネームを変更することは許可されていません"}. {"Visitors are not allowed to send messages to all occupants","ビジターが移住者ににメッセージを送ることは許可されていません"}. {"Wednesday","水曜日"}. diff --git a/src/msgs/ja.po b/src/msgs/ja.po index 2efb82439..7f19a828e 100644 --- a/src/msgs/ja.po +++ b/src/msgs/ja.po @@ -1352,8 +1352,8 @@ msgid "~s access rule configuration" msgstr "~s アクセスルール設定" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "ejabberd ヴァーチャルホスト" +msgid "Virtual Hosts" +msgstr "ヴァーチャルホスト" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1787,9 +1787,6 @@ msgstr "登録解除" #~ msgid "(Raw)" #~ msgstr "(Raw)" -#~ msgid "Virtual Hosts" -#~ msgstr "ヴァーチャルホスト" - #~ msgid "Specified nickname is already registered" #~ msgstr "指定されたニックネームは既に登録されています" diff --git a/src/msgs/nl.msg b/src/msgs/nl.msg index a105c5d11..d793d3dea 100644 --- a/src/msgs/nl.msg +++ b/src/msgs/nl.msg @@ -77,7 +77,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","ejabberd's vCard-module"}. -{"ejabberd virtual hosts","Virtuele hosts"}. {"ejabberd Web Admin","ejabberd Webbeheer"}. {"Elements","Elementen"}. {"Email","E-mail"}. @@ -362,6 +361,7 @@ {"Users Last Activity","Laatste activiteit van gebruikers"}. {"Validate","Bevestigen"}. {"vCard User Search","Gebruikers zoeken"}. +{"Virtual Hosts","Virtuele hosts"}. {"Visitors are not allowed to change their nicknames in this room","Het is bezoekers niet toegestaan hun naam te veranderen in dit kanaal"}. {"Visitors are not allowed to send messages to all occupants","Bezoekers mogen geen berichten verzenden naar alle aanwezigen"}. {"Wednesday","Woensdag"}. diff --git a/src/msgs/nl.po b/src/msgs/nl.po index 0057aaaa8..bf2254700 100644 --- a/src/msgs/nl.po +++ b/src/msgs/nl.po @@ -1378,7 +1378,7 @@ msgid "~s access rule configuration" msgstr "Access rules op ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" +msgid "Virtual Hosts" msgstr "Virtuele hosts" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 diff --git a/src/msgs/no.msg b/src/msgs/no.msg index eea9eb526..0d8adf85f 100644 --- a/src/msgs/no.msg +++ b/src/msgs/no.msg @@ -77,7 +77,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modul"}. {"ejabberd vCard module","ejabberd vCard modul"}. -{"ejabberd virtual hosts","virtuella ejabberd maskiner"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Elementer"}. {"Email","Epost"}. @@ -362,6 +361,7 @@ {"Users Last Activity","Brukers Siste Aktivitet"}. {"Validate","Bekrefte gyldighet"}. {"vCard User Search","vCard Bruker Søk"}. +{"Virtual Hosts","Virtuella Maskiner"}. {"Visitors are not allowed to change their nicknames in this room","Besøkende får ikke lov å endre kallenavn i dette "}. {"Visitors are not allowed to send messages to all occupants","Besøkende får ikke sende meldinger til alle deltakere"}. {"Wednesday","onsdag"}. diff --git a/src/msgs/no.po b/src/msgs/no.po index 560fe7fa7..cc66e81bb 100644 --- a/src/msgs/no.po +++ b/src/msgs/no.po @@ -1352,8 +1352,8 @@ msgid "~s access rule configuration" msgstr "tilgangsregel konfigurasjon for ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "virtuella ejabberd maskiner" +msgid "Virtual Hosts" +msgstr "Virtuella Maskiner" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/pl.msg b/src/msgs/pl.msg index 01083e38d..1dc68356b 100644 --- a/src/msgs/pl.msg +++ b/src/msgs/pl.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","Moduł Publish-Subscribe"}. {"ejabberd SOCKS5 Bytestreams module","Moduł SOCKS5 Bytestreams"}. {"ejabberd vCard module","Moduł vCard ejabberd"}. -{"ejabberd virtual hosts","wirtualne hosty ejabberd"}. {"ejabberd Web Admin","ejabberd: Panel Administracyjny"}. {"Elements","Elementy"}. {"Email","Email"}. @@ -388,6 +387,7 @@ {"User","Użytkownik"}. {"Validate","Potwierdź"}. {"vCard User Search","Wyszukiwanie vCard użytkowników"}. +{"Virtual Hosts","Wirtualne Hosty"}. {"Visitors are not allowed to change their nicknames in this room","Uczestnicy tego pokoju nie mogą zmieniać swoich nicków"}. {"Visitors are not allowed to send messages to all occupants","Odwiedzający nie mogą wysyłać wiadomości do wszystkich obecnych"}. {"Wednesday","Środa"}. diff --git a/src/msgs/pl.po b/src/msgs/pl.po index 28bfa21e1..bc3932b0a 100644 --- a/src/msgs/pl.po +++ b/src/msgs/pl.po @@ -1360,8 +1360,8 @@ msgid "~s access rule configuration" msgstr "~s konfiguracja zasad dostępu" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "wirtualne hosty ejabberd" +msgid "Virtual Hosts" +msgstr "Wirtualne Hosty" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/pt-br.msg b/src/msgs/pt-br.msg index f2cbf3e7f..f7c334751 100644 --- a/src/msgs/pt-br.msg +++ b/src/msgs/pt-br.msg @@ -78,7 +78,6 @@ {"ejabberd Publish-Subscribe module","Módulo para Publicar Tópicos do ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Modulo ejabberd SOCKS5 Bytestreams"}. {"ejabberd vCard module","Módulo vCard para ejabberd"}. -{"ejabberd virtual hosts","Hosts virtuais de ejabberd"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Elementos"}. {"Email","Email"}. @@ -376,6 +375,7 @@ {"User","Usuário"}. {"Validate","Validar"}. {"vCard User Search","Busca de Usuário vCard"}. +{"Virtual Hosts","Hosts virtuais"}. {"Visitors are not allowed to change their nicknames in this room","Nesta sala, os visitantes não pode mudar seus apelidos"}. {"Visitors are not allowed to send messages to all occupants","Os visitantes não podem enviar mensagens a todos os ocupantes"}. {"Wednesday","Quarta"}. diff --git a/src/msgs/pt-br.po b/src/msgs/pt-br.po index 59be6338a..e82979288 100644 --- a/src/msgs/pt-br.po +++ b/src/msgs/pt-br.po @@ -1368,8 +1368,8 @@ msgid "~s access rule configuration" msgstr "Configuração da Regra de Acesso ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Hosts virtuais de ejabberd" +msgid "Virtual Hosts" +msgstr "Hosts virtuais" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/pt.po b/src/msgs/pt.po index 25145e820..7758ac720 100644 --- a/src/msgs/pt.po +++ b/src/msgs/pt.po @@ -1425,8 +1425,8 @@ msgstr "Configuração das Regra de Acesso ~s" #: web/ejabberd_web_admin.erl:1031 #, fuzzy -msgid "ejabberd virtual hosts" -msgstr "Estatísticas do ejabberd" +msgid "Virtual Hosts" +msgstr "Servidores virtuales" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/ru.msg b/src/msgs/ru.msg index b618e6bde..3949ae07e 100644 --- a/src/msgs/ru.msg +++ b/src/msgs/ru.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","Модуль ejabberd Публикации-Подписки"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}. {"ejabberd vCard module","ejabberd vCard модуль"}. -{"ejabberd virtual hosts","Виртуальные хосты ejabberd"}. {"ejabberd Web Admin","Web-интерфейс администрирования ejabberd"}. {"Elements","Элементы"}. {"Email","Электронная почта"}. @@ -388,6 +387,7 @@ {"User","Пользователь"}. {"Validate","Утвердить"}. {"vCard User Search","Поиск пользователей по vCard"}. +{"Virtual Hosts","Виртуальные хосты"}. {"Visitors are not allowed to change their nicknames in this room","Посетителям запрещено изменять свои псевдонимы в этой комнате"}. {"Visitors are not allowed to send messages to all occupants","Посетителям не разрешается посылать сообщения всем присутствующим"}. {"Wednesday","Среда"}. diff --git a/src/msgs/ru.po b/src/msgs/ru.po index e4b567819..9f302d431 100644 --- a/src/msgs/ru.po +++ b/src/msgs/ru.po @@ -1363,8 +1363,8 @@ msgid "~s access rule configuration" msgstr "Конфигурация правила доступа ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Виртуальные хосты ejabberd" +msgid "Virtual Hosts" +msgstr "Виртуальные хосты" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/sk.msg b/src/msgs/sk.msg index 3f5b24ab8..3fd23a6df 100644 --- a/src/msgs/sk.msg +++ b/src/msgs/sk.msg @@ -77,7 +77,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modul"}. {"ejabberd vCard module","ejabberd vCard modul"}. -{"ejabberd virtual hosts","ejabberd virtuálne servery"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Prvky"}. {"Email","E-mail"}. @@ -362,6 +361,7 @@ {"User","Užívateľ"}. {"Validate","Overiť"}. {"vCard User Search","Hľadať užívateľov vo vCard"}. +{"Virtual Hosts","Virtuálne servery"}. {"Visitors are not allowed to change their nicknames in this room","V tejto miestnosti nieje povolené meniť prezývky"}. {"Visitors are not allowed to send messages to all occupants","Návštevníci nemajú povolené zasielať správy všetkým prihláseným do konferencie"}. {"Wednesday","Streda"}. diff --git a/src/msgs/sk.po b/src/msgs/sk.po index c35d815c8..ad766ca82 100644 --- a/src/msgs/sk.po +++ b/src/msgs/sk.po @@ -1355,8 +1355,8 @@ msgid "~s access rule configuration" msgstr "~s konfigurácia prístupového pravidla" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "ejabberd virtuálne servery" +msgid "Virtual Hosts" +msgstr "Virtuálne servery" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1788,9 +1788,6 @@ msgstr "" #~ msgid "(Raw)" #~ msgstr "(Raw)" -#~ msgid "Virtual Hosts" -#~ msgstr "Virtuálne servery" - #~ msgid "Specified nickname is already registered" #~ msgstr "Zadaná prezývka je už registrovaná" diff --git a/src/msgs/sv.msg b/src/msgs/sv.msg index 96aecf28a..fb69f9dce 100644 --- a/src/msgs/sv.msg +++ b/src/msgs/sv.msg @@ -72,7 +72,6 @@ {"ejabberd Publish-Subscribe module","ejabberd publikprenumerations modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestrem modul"}. {"ejabberd vCard module","ejabberd vCard-modul"}. -{"ejabberd virtual hosts","Virtuella ejabberd-servrar"}. {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Elements"}. {"Email","Email"}. @@ -348,6 +347,7 @@ {"Users Last Activity","Användarens senaste aktivitet"}. {"Validate","Validera"}. {"vCard User Search","vCard användare sök"}. +{"Virtual Hosts","Virtuella servrar"}. {"Visitors are not allowed to change their nicknames in this room","Det är inte tillåtet for gäster att ändra sina smeknamn i detta rummet"}. {"Visitors are not allowed to send messages to all occupants","Besökare får inte skicka medelande till alla"}. {"Wednesday","Onsdag"}. diff --git a/src/msgs/sv.po b/src/msgs/sv.po index db5d1186f..6fa9b7110 100644 --- a/src/msgs/sv.po +++ b/src/msgs/sv.po @@ -1371,8 +1371,8 @@ msgid "~s access rule configuration" msgstr "Åtkomstregelkonfiguration för ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Virtuella ejabberd-servrar" +msgid "Virtual Hosts" +msgstr "Virtuella servrar" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/th.msg b/src/msgs/th.msg index 74edb47b5..892fe48bb 100644 --- a/src/msgs/th.msg +++ b/src/msgs/th.msg @@ -66,7 +66,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","ejabberd vCard module"}. -{"ejabberd virtual hosts","โฮสต์เสมือน ejabberd"}. {"Email","อีเมล"}. {"Enable logging","เปิดใช้งานการบันทึก"}. {"End User Session","สิ้นสุดเซสชันของผู้ใช้"}. @@ -297,6 +296,7 @@ {"Users Last Activity","กิจกรรมล่าสุดของผู้ใช้"}. {"Validate","ตรวจสอบ"}. {"vCard User Search","ค้นหาผู้ใช้ vCard "}. +{"Virtual Hosts","โฮสต์เสมือน"}. {"Visitors are not allowed to send messages to all occupants","ผู้เยี่ยมเยือนไม่ได้รับอนุญาตให้ส่งข้อความถึงผู้ครอบครองห้องทั้งหมด"}. {"Wednesday","วันพุธ"}. {"When to send the last published item","เวลาที่ส่งรายการที่เผยแพร่ครั้งล่าสุด"}. diff --git a/src/msgs/th.po b/src/msgs/th.po index 36b5151e1..4a2aabdeb 100644 --- a/src/msgs/th.po +++ b/src/msgs/th.po @@ -1372,8 +1372,8 @@ msgid "~s access rule configuration" msgstr "~s การกำหนดค่ากฎการเข้าถึง" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "โฮสต์เสมือน ejabberd" +msgid "Virtual Hosts" +msgstr "โฮสต์เสมือน" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1803,9 +1803,6 @@ msgstr "" #~ msgid "(Raw)" #~ msgstr "(ข้อมูลดิบ)" -#~ msgid "Virtual Hosts" -#~ msgstr "โฮสต์เสมือน" - #~ msgid "Specified nickname is already registered" #~ msgstr "ชื่อเล่นที่ระบุได้รับการลงได้ทะเบียนแล้ว" diff --git a/src/msgs/tr.msg b/src/msgs/tr.msg index beff9c153..014b7c81a 100644 --- a/src/msgs/tr.msg +++ b/src/msgs/tr.msg @@ -73,7 +73,6 @@ {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modülü"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modülü"}. {"ejabberd vCard module","ejabberd vCard modülü"}. -{"ejabberd virtual hosts","ejabberd sanal sunucuları"}. {"ejabberd Web Admin","ejabberd Web Yöneticisi"}. {"Elements","Elementler"}. {"Email","E-posta"}. @@ -356,6 +355,7 @@ {"Users Last Activity","Kullanıcıların Son Aktiviteleri"}. {"Validate","Geçerli"}. {"vCard User Search","vCard Kullanıcı Araması"}. +{"Virtual Hosts","Sanal Sunucuları"}. {"Visitors are not allowed to change their nicknames in this room","Bu odada ziyaretçilerin takma isimlerini değiştirmesine izin verilmiyor"}. {"Visitors are not allowed to send messages to all occupants","Ziyaretçilerin odadaki tüm sakinlere mesaj göndermesine izin verilmiyor"}. {"Wednesday","Çarşamba"}. diff --git a/src/msgs/tr.po b/src/msgs/tr.po index 11e88f569..333eaa5c3 100644 --- a/src/msgs/tr.po +++ b/src/msgs/tr.po @@ -1375,8 +1375,8 @@ msgid "~s access rule configuration" msgstr "~s erişim kuralları ayarları" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "ejabberd sanal sunucuları" +msgid "Virtual Hosts" +msgstr "Sanal Sunucuları" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/uk.msg b/src/msgs/uk.msg index cf1e6a8db..4da7e09dc 100644 --- a/src/msgs/uk.msg +++ b/src/msgs/uk.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","Модуль ejabberd Публікації-Абонування"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}. {"ejabberd vCard module","ejabberd vCard модуль"}. -{"ejabberd virtual hosts","віртуальні хости ejabberd"}. {"ejabberd Web Admin","Веб-інтерфейс Адміністрування ejabberd"}. {"Elements","Елементи"}. {"Email","Електронна пошта"}. @@ -388,6 +387,7 @@ {"User","Користувач"}. {"Validate","Затвердити"}. {"vCard User Search","Пошук користувачів по vCard"}. +{"Virtual Hosts","віртуальні хости"}. {"Visitors are not allowed to change their nicknames in this room","Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті"}. {"Visitors are not allowed to send messages to all occupants","Відвідувачам не дозволяється надсилати повідомлення всім присутнім"}. {"Wednesday","Середа"}. diff --git a/src/msgs/uk.po b/src/msgs/uk.po index 2b1b195f9..92c3ab3f7 100644 --- a/src/msgs/uk.po +++ b/src/msgs/uk.po @@ -1368,8 +1368,8 @@ msgid "~s access rule configuration" msgstr "Конфігурація правила доступу ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "віртуальні хости ejabberd" +msgid "Virtual Hosts" +msgstr "віртуальні хости" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" diff --git a/src/msgs/vi.msg b/src/msgs/vi.msg index a773c4cc6..da3101110 100644 --- a/src/msgs/vi.msg +++ b/src/msgs/vi.msg @@ -66,7 +66,6 @@ {"ejabberd Publish-Subscribe module","Môdun ejabberd Xuất Bản-Đăng Ký Bản quyền"}. {"ejabberd SOCKS5 Bytestreams module","Môdun SOCKS5 Bytestreams Bản quyền"}. {"ejabberd vCard module","Môdun ejabberd vCard Bản quyền"}. -{"ejabberd virtual hosts","Máy chủ ảo ejabberd"}. {"Email","Email"}. {"Enable logging","Cho phép ghi nhật ký"}. {"End User Session","Kết Thúc Phiên Giao Dịch Người Sử Dụng"}. @@ -297,6 +296,7 @@ {"Users","Người sử dụng"}. {"Validate","Xác nhận hợp lệ"}. {"vCard User Search","Tìm Kiếm Người Sử Dụng vCard"}. +{"Virtual Hosts","Máy Chủ Ảo"}. {"Visitors are not allowed to send messages to all occupants","Người ghé thăm không được phép gửi thư đến tất cả các người tham dự"}. {"Wednesday","Thứ Tư"}. {"When to send the last published item","Khi cần gửi mục được xuất bản cuối cùng"}. diff --git a/src/msgs/vi.po b/src/msgs/vi.po index 5132061d7..721caab88 100644 --- a/src/msgs/vi.po +++ b/src/msgs/vi.po @@ -1395,8 +1395,8 @@ msgid "~s access rule configuration" msgstr "~s cấu hình quy tắc truy cập" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Máy chủ ảo ejabberd" +msgid "Virtual Hosts" +msgstr "Máy Chủ Ảo" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1828,9 +1828,6 @@ msgstr "" #~ msgid "(Raw)" #~ msgstr "(Thô)" -#~ msgid "Virtual Hosts" -#~ msgstr "Máy Chủ Ảo" - #~ msgid "Specified nickname is already registered" #~ msgstr "Bí danh xác định đã đăng ký rồi" diff --git a/src/msgs/wa.msg b/src/msgs/wa.msg index 327a08fac..199a6eaf8 100644 --- a/src/msgs/wa.msg +++ b/src/msgs/wa.msg @@ -69,7 +69,6 @@ {"ejabberd Publish-Subscribe module","Module d' eplaidaedje-abounmint po ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Module SOCKS5 Bytestreams po ejabberd"}. {"ejabberd vCard module","Module vCard ejabberd"}. -{"ejabberd virtual hosts","Forveyous sierveus da ejabberd"}. {"ejabberd Web Admin","Manaedjeu waibe ejabberd"}. {"Email","Emile"}. {"Enable logging","Mete en alaedje li djournå"}. @@ -310,6 +309,7 @@ {"User","Uzeu"}. {"Validate","Valider"}. {"vCard User Search","Calpin des uzeus"}. +{"Virtual Hosts","Forveyous sierveus"}. {"Visitors are not allowed to change their nicknames in this room","Les viziteus èn polèt nén candjî leus metous no po ç' såle ci"}. {"Visitors are not allowed to send messages to all occupants","Les viziteus n' polèt nén evoyî des messaedjes a tos les prezints"}. {"Wednesday","mierkidi"}. diff --git a/src/msgs/wa.po b/src/msgs/wa.po index 4e3a664e2..b3ac7c799 100644 --- a/src/msgs/wa.po +++ b/src/msgs/wa.po @@ -1393,8 +1393,8 @@ msgid "~s access rule configuration" msgstr "Apontiaedje des rîles d' accès a ~s" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "Forveyous sierveus da ejabberd" +msgid "Virtual Hosts" +msgstr "Forveyous sierveus" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1827,9 +1827,6 @@ msgstr "" #~ msgid "(Raw)" #~ msgstr "(Dinêyes brutes)" -#~ msgid "Virtual Hosts" -#~ msgstr "Forveyous sierveus" - #~ msgid "Specified nickname is already registered" #~ msgstr "Li no metou dné est ddja edjîstré" diff --git a/src/msgs/zh.msg b/src/msgs/zh.msg index b025b16d2..e13cd154f 100644 --- a/src/msgs/zh.msg +++ b/src/msgs/zh.msg @@ -80,7 +80,6 @@ {"ejabberd Publish-Subscribe module","ejabberd 发行-订阅模块"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 字节流模块"}. {"ejabberd vCard module","ejabberd vCard 模块"}. -{"ejabberd virtual hosts","ejabberd 虚拟主机"}. {"ejabberd Web Admin","ejabberd 网页管理"}. {"Elements","元素"}. {"Email","电子邮件"}. @@ -388,6 +387,7 @@ {"User","用户"}. {"Validate","确认"}. {"vCard User Search","vCard 用户搜索"}. +{"Virtual Hosts","虚拟主机"}. {"Visitors are not allowed to change their nicknames in this room","此房间不允许用户更改昵称"}. {"Visitors are not allowed to send messages to all occupants","不允许访客给所有占有者发送消息"}. {"Wednesday","星期三"}. diff --git a/src/msgs/zh.po b/src/msgs/zh.po index bd740c004..cb55bce26 100644 --- a/src/msgs/zh.po +++ b/src/msgs/zh.po @@ -1338,8 +1338,8 @@ msgid "~s access rule configuration" msgstr "~s 访问规则配置" #: web/ejabberd_web_admin.erl:1031 -msgid "ejabberd virtual hosts" -msgstr "ejabberd 虚拟主机" +msgid "Virtual Hosts" +msgstr "虚拟主机" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1765,9 +1765,6 @@ msgstr "取消注册" #~ msgid "(Raw)" #~ msgstr "(原始格式)" -#~ msgid "Virtual Hosts" -#~ msgstr "虚拟主机" - #~ msgid "Specified nickname is already registered" #~ msgstr "指定的昵称已被注册" From e4b3bd50055aca9aaba576bdc653209bc394bb23 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 17 Mar 2011 12:15:31 +0100 Subject: [PATCH 14/47] Fix typo (thanks to Krzee) --- src/ejabberdctl.cfg.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberdctl.cfg.example b/src/ejabberdctl.cfg.example index fe703242e..2106e3d22 100644 --- a/src/ejabberdctl.cfg.example +++ b/src/ejabberdctl.cfg.example @@ -66,7 +66,7 @@ INET_DIST_INTERFACE={127,0,0,1} # # Erlang consumes a lot of lightweight processes. If there is a lot of activity # on ejabberd so that the maximum number of processes is reached, people will -# experiment greater latency times. As these processes are implemented in +# experience greater latency times. As these processes are implemented in # Erlang, and therefore not related to the operating system processes, you do # not have to worry about allowing a huge number of them. # From 90ea752046c5467520214f6da72ba9e825a45843 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 28 Mar 2011 18:37:28 +0200 Subject: [PATCH 15/47] Updated Japanese translation (thanks to Mako N) --- src/msgs/ja.po | 360 +++++++++++++++++++++++++------------------------ 1 file changed, 183 insertions(+), 177 deletions(-) diff --git a/src/msgs/ja.po b/src/msgs/ja.po index 7f19a828e..2c11e4347 100644 --- a/src/msgs/ja.po +++ b/src/msgs/ja.po @@ -1,15 +1,17 @@ msgid "" msgstr "" -"Project-Id-Version: 2.1.0-alpha\n" -"Last-Translator: Tsukasa Hamano\n" +"Project-Id-Version: ejabberd 2.1.x\n" +"PO-Revision-Date: 2010-12-24 18:46+0900\n" +"Last-Translator: Mako N \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Japanese (日本語)\n" +"X-Additional-Translator: Tsukasa Hamano \n" #: ejabberd_c2s.erl:424 ejabberd_c2s.erl:727 msgid "Use of STARTTLS required" -msgstr "STARTTLS を使用" +msgstr "STARTTLS の使用が必要です" #: ejabberd_c2s.erl:503 msgid "No resource provided" @@ -34,15 +36,15 @@ msgstr "" #: ejabberd_captcha.erl:132 msgid "If you don't see the CAPTCHA image here, visit the web page." -msgstr "ここにキャプチャ画像が表示されない場合、WEBページを参照してください。" +msgstr "ここに CAPTCHA 画像が表示されない場合、web ページを参照してください。" #: ejabberd_captcha.erl:144 msgid "CAPTCHA web page" -msgstr "キャプチャWEBページ" +msgstr "CAPTCHA web ページ" #: ejabberd_captcha.erl:302 msgid "The captcha is valid." -msgstr "キャプチャは有効です。" +msgstr "CAPTCHA は有効です。" #: mod_adhoc.erl:95 mod_adhoc.erl:125 mod_adhoc.erl:143 mod_adhoc.erl:161 msgid "Commands" @@ -58,7 +60,7 @@ msgstr "Pong" #: mod_announce.erl:506 msgid "Really delete message of the day?" -msgstr "本当にお知らせメッセージを削除しますか?" +msgstr "本当にお知らせメッセージを削除しますか ?" #: mod_announce.erl:514 mod_configure.erl:1083 mod_configure.erl:1128 msgid "Subject" @@ -78,43 +80,43 @@ msgstr "アナウンス" #: mod_announce.erl:636 msgid "Send announcement to all users" -msgstr "アナウンスを全てのユーザーに送信" +msgstr "すべてのユーザーにアナウンスを送信" #: mod_announce.erl:638 msgid "Send announcement to all users on all hosts" -msgstr "アナウンスを全ホストのユーザーに送信" +msgstr "全ホストのユーザーにアナウンスを送信" #: mod_announce.erl:640 msgid "Send announcement to all online users" -msgstr "アナウンスを全てのオンラインユーザーに送信" +msgstr "すべてのオンラインユーザーにアナウンスを送信" #: mod_announce.erl:642 mod_configure.erl:1078 mod_configure.erl:1123 msgid "Send announcement to all online users on all hosts" -msgstr "全ホストのオンラインユーザへアナウンスを送信" +msgstr "全ホストのオンラインユーザーにアナウンスを送信" #: mod_announce.erl:644 msgid "Set message of the day and send to online users" -msgstr "お知らせメッセージを設定し、オンラインユーザーに送信する" +msgstr "お知らせメッセージを設定し、オンラインユーザーに送信" #: mod_announce.erl:646 msgid "Set message of the day on all hosts and send to online users" -msgstr "全ホストのお知らせメッセージを設定し、オンラインユーザーに送信する" +msgstr "全ホストのお知らせメッセージを設定し、オンラインユーザーに送信" #: mod_announce.erl:648 msgid "Update message of the day (don't send)" -msgstr "お知らせメッセージを更新する(送信しない)" +msgstr "お知らせメッセージを更新 (送信しない)" #: mod_announce.erl:650 msgid "Update message of the day on all hosts (don't send)" -msgstr "全ホストのお知らせメッセージを更新する" +msgstr "全ホストのお知らせメッセージを更新 (送信しない)" #: mod_announce.erl:652 msgid "Delete message of the day" -msgstr "お知らせメッセージを削除する" +msgstr "お知らせメッセージを削除" #: mod_announce.erl:654 msgid "Delete message of the day on all hosts" -msgstr "全ホストのお知らせメッセージを削除する" +msgstr "全ホストのお知らせメッセージを削除" #: mod_configure.erl:114 mod_configure.erl:274 mod_configure.erl:296 #: mod_configure.erl:498 @@ -127,11 +129,11 @@ msgstr "データーベース" #: mod_configure.erl:127 mod_configure.erl:595 msgid "Start Modules" -msgstr "モジュールの起動" +msgstr "モジュールを起動" #: mod_configure.erl:129 mod_configure.erl:596 msgid "Stop Modules" -msgstr "モジュールの停止" +msgstr "モジュールを停止" #: mod_configure.erl:131 mod_configure.erl:604 web/ejabberd_web_admin.erl:1931 msgid "Backup" @@ -147,7 +149,7 @@ msgstr "テキストファイルに出力" #: mod_configure.erl:137 mod_configure.erl:615 msgid "Import File" -msgstr "ファイルかインポート" +msgstr "ファイルからインポート" #: mod_configure.erl:139 mod_configure.erl:616 msgid "Import Directory" @@ -168,7 +170,7 @@ msgstr "ユーザーを追加" #: mod_configure.erl:147 mod_configure.erl:519 mod_configure.erl:1219 msgid "Delete User" -msgstr "ユーザを削除" +msgstr "ユーザーを削除" #: mod_configure.erl:149 mod_configure.erl:520 mod_configure.erl:1231 msgid "End User Session" @@ -185,11 +187,11 @@ msgstr "パスワードを変更" #: mod_configure.erl:155 mod_configure.erl:523 mod_configure.erl:1272 msgid "Get User Last Login Time" -msgstr "最終ログイン時間の取得" +msgstr "最終ログイン時間を取得" #: mod_configure.erl:157 mod_configure.erl:524 mod_configure.erl:1284 msgid "Get User Statistics" -msgstr "ユーザー統計の取得" +msgstr "ユーザー統計を取得" #: mod_configure.erl:159 mod_configure.erl:525 msgid "Get Number of Registered Users" @@ -197,7 +199,7 @@ msgstr "登録ユーザー数を取得" #: mod_configure.erl:161 mod_configure.erl:526 msgid "Get Number of Online Users" -msgstr "登録ユーザーを取得" +msgstr "オンラインユーザー数を取得" #: mod_configure.erl:163 mod_configure.erl:509 web/ejabberd_web_admin.erl:827 #: web/ejabberd_web_admin.erl:868 @@ -260,7 +262,7 @@ msgstr "データーベーステーブル設定 " #: mod_configure.erl:918 msgid "Choose storage type of tables" -msgstr "テーブルのストレージタイプの選択" +msgstr "テーブルのストレージタイプを選択" #: mod_configure.erl:926 mod_configure.erl:928 msgid "Disc only copy" @@ -280,19 +282,19 @@ msgstr "リモートコピー" #: mod_configure.erl:950 msgid "Stop Modules at " -msgstr "モジュールの停止 " +msgstr "モジュールを停止: " #: mod_configure.erl:954 msgid "Choose modules to stop" -msgstr "停止するモジュールの選択" +msgstr "停止するモジュールを選択" #: mod_configure.erl:969 msgid "Start Modules at " -msgstr "モジュールの開始" +msgstr "モジュールを開始: " #: mod_configure.erl:973 msgid "Enter list of {Module, [Options]}" -msgstr "{モジュール, [オプション]}のリストを入力して下さい" +msgstr "{モジュール, [オプション]}のリストを入力してください" #: mod_configure.erl:974 msgid "List of modules to start" @@ -300,44 +302,44 @@ msgstr "起動モジュールの一覧" #: mod_configure.erl:983 msgid "Backup to File at " -msgstr "ファイルにバックアップ" +msgstr "ファイルにバックアップ: " #: mod_configure.erl:987 mod_configure.erl:1001 msgid "Enter path to backup file" -msgstr "バックアップファイルのパスを入力して下さい" +msgstr "バックアップファイルのパスを入力してください" #: mod_configure.erl:988 mod_configure.erl:1002 mod_configure.erl:1016 #: mod_configure.erl:1030 msgid "Path to File" -msgstr "ファイルパス" +msgstr "ファイルのパス" #: mod_configure.erl:997 msgid "Restore Backup from File at " -msgstr "ファイルからバックアップをリストア" +msgstr "ファイルからバックアップをリストア: " #: mod_configure.erl:1011 msgid "Dump Backup to Text File at " -msgstr "テキストファイルにバックアップ" +msgstr "テキストファイルにバックアップ: " #: mod_configure.erl:1015 msgid "Enter path to text file" -msgstr "テキストファイルのパスを入力して下さい" +msgstr "テキストファイルのパスを入力してください" #: mod_configure.erl:1025 msgid "Import User from File at " -msgstr "ファイルからユーザーをインポート" +msgstr "ファイルからユーザーをインポート: " #: mod_configure.erl:1029 msgid "Enter path to jabberd14 spool file" -msgstr "jabberd14 spool ファイルのパスを入力して下さい" +msgstr "jabberd14 spool ファイルのパスを入力してください" #: mod_configure.erl:1039 msgid "Import Users from Dir at " -msgstr "ディレクトリからユーザーをインポート" +msgstr "ディレクトリからユーザーをインポート: " #: mod_configure.erl:1043 msgid "Enter path to jabberd14 spool dir" -msgstr "jabberd14 spool ディレクトリのパスを入力して下さい" +msgstr "jabberd14 spool ディレクトリのディレクトリを入力してください" #: mod_configure.erl:1044 msgid "Path to Dir" @@ -379,7 +381,7 @@ msgstr "パスワード" #: mod_configure.erl:1210 msgid "Password Verification" -msgstr "パスワード(確認)" +msgstr "パスワード (確認)" #: mod_configure.erl:1301 msgid "Number of registered users" @@ -392,7 +394,7 @@ msgstr "オンラインユーザー数" #: mod_configure.erl:1684 web/ejabberd_web_admin.erl:1585 #: web/ejabberd_web_admin.erl:1737 msgid "Never" -msgstr "無し" +msgstr "なし" #: mod_configure.erl:1698 web/ejabberd_web_admin.erl:1598 #: web/ejabberd_web_admin.erl:1750 @@ -425,11 +427,11 @@ msgstr "ユーザー操作" #: mod_configure.erl:1859 msgid "Edit Properties" -msgstr "プロパティの編集" +msgstr "プロパティを編集" #: mod_configure.erl:1862 web/ejabberd_web_admin.erl:1763 msgid "Remove User" -msgstr "ユーザーの削除" +msgstr "ユーザーを削除" #: mod_irc/mod_irc.erl:201 mod_muc/mod_muc.erl:336 msgid "Access denied by service policy" @@ -456,12 +458,12 @@ msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" -"IRCサーバーに接続先する為に、使用するユーザー名、文字エンコーディング、ポー" -"ト、パスワードを入力して下さい" +"IRC サーバーに接続先するために使用するユーザー名、文字エンコーディング、ポー" +"ト、パスワードを入力してください" #: mod_irc/mod_irc.erl:575 msgid "IRC Username" -msgstr "IRCユーザー名" +msgstr "IRC ユーザー名" #: mod_irc/mod_irc.erl:585 msgid "" @@ -471,8 +473,8 @@ msgid "" "~p, empty password." msgstr "" "別のポートやパスワード、文字エンコーディングを使用したい場合、'{\"irc server" -"\", \"encoding\", port, \"password\"}' という形式のリストを入力して下さい。デ" -"フォルトでエンコーディングは \"~s\" を使用し、ポートは ~p、パスワードは空に" +"\", \"encoding\", port, \"password\"}' という形式のリストを入力してください。" +"デフォルトでエンコーディングは \"~s\" を使用し、ポートは ~p、パスワードは空に" "なっています。" #: mod_irc/mod_irc.erl:597 @@ -489,27 +491,27 @@ msgstr "接続パラメータ" #: mod_irc/mod_irc.erl:727 msgid "Join IRC channel" -msgstr "IRCチャンネルに参加" +msgstr "IRC チャンネルに参加" #: mod_irc/mod_irc.erl:731 msgid "IRC channel (don't put the first #)" -msgstr "IRCチャンネル(先頭に#は不要)" +msgstr "IRC チャンネル (先頭に#は不要)" #: mod_irc/mod_irc.erl:736 msgid "IRC server" -msgstr "IRCサーバー" +msgstr "IRC サーバー" #: mod_irc/mod_irc.erl:769 mod_irc/mod_irc.erl:773 msgid "Join the IRC channel here." -msgstr "このIRCチャンネルに参加" +msgstr "この IRC チャンネルに参加します。" #: mod_irc/mod_irc.erl:777 msgid "Join the IRC channel in this Jabber ID: ~s" -msgstr "Jabber ID: ~s でIRCチャンネルに参加" +msgstr "Jabber ID: ~s でこの IRC チャンネルに参加" #: mod_irc/mod_irc.erl:862 msgid "IRC settings" -msgstr "IRC設定" +msgstr "IRC 設定" #: mod_irc/mod_irc.erl:867 msgid "" @@ -517,13 +519,13 @@ msgid "" "Press 'Next' to get more fields to fill in. Press 'Complete' to save " "settings." msgstr "" -"IRCサーバーに接続先する為のユーザー名と文字エンコーディングを入力して下さ" -"い。'Next' を押して次の項目に進みます。'Complete' を押すと設定が保存されま" +"IRC サーバーに接続先するためのユーザー名と文字エンコーディングを入力してくだ" +"さい。'Next' を押して次の項目に進みます。'Complete' を押すと設定が保存されま" "す。" #: mod_irc/mod_irc.erl:873 msgid "IRC username" -msgstr "IRCユーザー名" +msgstr "IRC ユーザー名" #: mod_irc/mod_irc.erl:922 msgid "Password ~b" @@ -543,7 +545,7 @@ msgstr "サーバー ~b" #: mod_muc/mod_muc.erl:449 msgid "Only service administrators are allowed to send service messages" -msgstr "カービス管理者のみがサービスメッセージを送信出来ます" +msgstr "サービス管理者のみがサービスメッセージを送信できます" #: mod_muc/mod_muc.erl:493 msgid "Room creation is denied by service policy" @@ -568,7 +570,7 @@ msgstr "ニックネーム登録: " #: mod_muc/mod_muc.erl:721 msgid "Enter nickname you want to register" -msgstr "登録するニックネームを入力して下さい" +msgstr "登録するニックネームを入力してください" #: mod_muc/mod_muc.erl:722 mod_roster.erl:949 mod_roster_odbc.erl:1049 #: mod_vcard.erl:358 mod_vcard.erl:471 mod_vcard_odbc.erl:336 @@ -579,7 +581,7 @@ msgstr "ニックネーム" #: mod_muc/mod_muc.erl:761 mod_muc/mod_muc_room.erl:936 #: mod_muc/mod_muc_room.erl:1580 msgid "That nickname is registered by another person" -msgstr "ニックネームは他の人によって登録されています" +msgstr "ニックネームはほかの人によって登録されています" #: mod_muc/mod_muc.erl:787 msgid "You must fill in field \"Nickname\" in the form" @@ -591,15 +593,15 @@ msgstr "ejabberd MUC module" #: mod_muc/mod_muc_log.erl:374 mod_muc/mod_muc_log.erl:381 msgid "Chatroom configuration modified" -msgstr "チャットルームの設定を変更しました" +msgstr "チャットルームの設定が変更されました" #: mod_muc/mod_muc_log.erl:384 msgid "joins the room" -msgstr "チャットルームに参加" +msgstr "がチャットルームに参加しました" #: mod_muc/mod_muc_log.erl:387 mod_muc/mod_muc_log.erl:390 msgid "leaves the room" -msgstr "チャットルームから退出" +msgstr "がチャットルームから退出しました" #: mod_muc/mod_muc_log.erl:393 mod_muc/mod_muc_log.erl:396 msgid "has been banned" @@ -611,11 +613,11 @@ msgstr "はキックされました" #: mod_muc/mod_muc_log.erl:405 msgid "has been kicked because of an affiliation change" -msgstr "は提携が変更されたためキックされました" +msgstr "は分掌が変更されたためキックされました" #: mod_muc/mod_muc_log.erl:408 msgid "has been kicked because the room has been changed to members-only" -msgstr "はチャットルームのメンバー制限によりキックされました" +msgstr "はチャットルームのメンバーのみに変更されたためキックされました" #: mod_muc/mod_muc_log.erl:411 msgid "has been kicked because of a system shutdown" @@ -632,19 +634,19 @@ msgstr " は件名を設定しました: " #: mod_muc/mod_muc_log.erl:452 msgid "Chatroom is created" -msgstr "チャットルームは作られました。" +msgstr "チャットルームを作りました" #: mod_muc/mod_muc_log.erl:453 msgid "Chatroom is destroyed" -msgstr "チャットルームは削除されました。" +msgstr "チャットルームを削除しました" #: mod_muc/mod_muc_log.erl:454 msgid "Chatroom is started" -msgstr "チャットルームが開始しました。" +msgstr "チャットルームを開始しました" #: mod_muc/mod_muc_log.erl:455 msgid "Chatroom is stopped" -msgstr "チャットルームが停止しました。" +msgstr "チャットルームを停止しました" #: mod_muc/mod_muc_log.erl:459 msgid "Monday" @@ -728,7 +730,7 @@ msgstr "チャットルーム設定" #: mod_muc/mod_muc_log.erl:760 msgid "Room Occupants" -msgstr "居住者の数" +msgstr "在室者の数" #: mod_muc/mod_muc_room.erl:170 msgid "Traffic rate limit is exceeded" @@ -741,7 +743,7 @@ msgstr "エラーメッセージを送信したため、この参加者はキッ #: mod_muc/mod_muc_room.erl:251 msgid "It is not allowed to send private messages to the conference" -msgstr "カンファレンスルームにプライベートメッセージを送信することは出来ません" +msgstr "カンファレンスルームにプライベートメッセージを送信することはできません" #: mod_muc/mod_muc_room.erl:296 msgid "Improper message type" @@ -756,44 +758,44 @@ msgstr "" #: mod_muc/mod_muc_room.erl:419 msgid "It is not allowed to send private messages of type \"groupchat\"" -msgstr "種別が\"groupchat\" であるプライベートメッセージは許可されていません" +msgstr "" +"種別が\"groupchat\" であるプライベートメッセージを送信することはできません" #: mod_muc/mod_muc_room.erl:431 mod_muc/mod_muc_room.erl:486 msgid "Recipient is not in the conference room" -msgstr "受信者がカンファレンスルームに居ません" +msgstr "受信者がカンファレンスルームにいません" #: mod_muc/mod_muc_room.erl:451 mod_muc/mod_muc_room.erl:829 #: mod_muc/mod_muc_room.erl:3546 msgid "Only occupants are allowed to send messages to the conference" -msgstr "移住者のみがカンファレンスに" +msgstr "在室者のみがカンファレンスにメッセージを送ることができます" #: mod_muc/mod_muc_room.erl:460 msgid "It is not allowed to send private messages" -msgstr "プライベートメッセージを送信することは許可されませんでした" +msgstr "プライベートメッセージを送信することはできません" #: mod_muc/mod_muc_room.erl:509 msgid "Only occupants are allowed to send queries to the conference" -msgstr "移住者のみがカンファレンスにクエリーを送信出来ます" +msgstr "在室者のみがカンファレンスにクエリーを送信することができます" #: mod_muc/mod_muc_room.erl:521 msgid "Queries to the conference members are not allowed in this room" msgstr "" -"このチャットルームではカンファレンスメンバーへのクエリーは禁止されています" +"このチャットルームでは、カンファレンスメンバーへのクエリーは禁止されています" #: mod_muc/mod_muc_room.erl:805 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" -msgstr "" -"モデレーターと参加者のみがチャットルームの件名を変更する事を許可されています" +msgstr "モデレーターと参加者のみがチャットルームの件名を変更できます" #: mod_muc/mod_muc_room.erl:810 msgid "Only moderators are allowed to change the subject in this room" -msgstr "モデレーターのみがチャットルームの件名を変更出来ます" +msgstr "モデレーターのみがチャットルームの件名を変更できます" #: mod_muc/mod_muc_room.erl:820 msgid "Visitors are not allowed to send messages to all occupants" -msgstr "ビジターが移住者ににメッセージを送ることは許可されていません" +msgstr "ビジターはすべての在室者にメッセージを送信することはできません" #: mod_muc/mod_muc_room.erl:894 msgid "" @@ -802,12 +804,11 @@ msgstr "エラープレゼンスを送信したため、この参加者はキッ #: mod_muc/mod_muc_room.erl:912 msgid "Visitors are not allowed to change their nicknames in this room" -msgstr "" -"ビジターはこのチャットルームでニックネームを変更することは許可されていません" +msgstr "ビジターはこのチャットルームでニックネームを変更することはできません" #: mod_muc/mod_muc_room.erl:925 mod_muc/mod_muc_room.erl:1572 msgid "That nickname is already in use by another occupant" -msgstr "ニックネームは既に他の移住者によって使用されています" +msgstr "ニックネームは既にほかの在室者によって使用されています" #: mod_muc/mod_muc_room.erl:1561 msgid "You have been banned from this room" @@ -827,7 +828,7 @@ msgstr "チャットルームに入るにはパスワードが必要です" #: mod_muc/mod_muc_room.erl:1648 msgid "Unable to generate a captcha" -msgstr "キャプチャを生成することが出来ません。" +msgstr "CAPTCHA を生成することができません" #: mod_muc/mod_muc_room.erl:1658 msgid "Incorrect password" @@ -847,15 +848,15 @@ msgstr "Jabber ID ~s は無効です" #: mod_muc/mod_muc_room.erl:2354 msgid "Nickname ~s does not exist in the room" -msgstr "ニックネーム ~s はこのチャットルームに居ません" +msgstr "ニックネーム ~s はこのチャットルームにいません" #: mod_muc/mod_muc_room.erl:2380 mod_muc/mod_muc_room.erl:2762 msgid "Invalid affiliation: ~s" -msgstr "無効な提携です: ~s" +msgstr "無効な分掌です: ~s" #: mod_muc/mod_muc_room.erl:2437 msgid "Invalid role: ~s" -msgstr "無効なロールです: ~s" +msgstr "無効な役です: ~s" #: mod_muc/mod_muc_room.erl:2739 mod_muc/mod_muc_room.erl:2775 msgid "Owner privileges required" @@ -871,35 +872,35 @@ msgstr "チャットルームタイトル" #: mod_muc/mod_muc_room.erl:2907 mod_muc/mod_muc_room.erl:3325 msgid "Room description" -msgstr "チャットルームの詳細" +msgstr "チャットルームの説明" #: mod_muc/mod_muc_room.erl:2914 msgid "Make room persistent" -msgstr "チャットルームを永続化します" +msgstr "チャットルームを永続化" #: mod_muc/mod_muc_room.erl:2919 msgid "Make room public searchable" -msgstr "チャットルームを検索可能にします" +msgstr "チャットルームを検索可" #: mod_muc/mod_muc_room.erl:2922 msgid "Make participants list public" -msgstr "参加者一覧を公開します" +msgstr "参加者一覧を公開" #: mod_muc/mod_muc_room.erl:2925 msgid "Make room password protected" -msgstr "チャットルームにパスワードを設定します" +msgstr "チャットルームにパスワードを設定" #: mod_muc/mod_muc_room.erl:2936 msgid "Maximum Number of Occupants" -msgstr "最大移住者数" +msgstr "最大在室者数" #: mod_muc/mod_muc_room.erl:2943 msgid "No limit" -msgstr "制限無し" +msgstr "制限なし" #: mod_muc/mod_muc_room.erl:2954 msgid "Present real Jabber IDs to" -msgstr "本当の Jabber ID を公開する" +msgstr "本当の Jabber ID を公開" #: mod_muc/mod_muc_room.erl:2962 msgid "moderators only" @@ -911,61 +912,61 @@ msgstr "誰でも" #: mod_muc/mod_muc_room.erl:2966 msgid "Make room members-only" -msgstr "チャットルームをメンバーのみに制限する" +msgstr "チャットルームをメンバーのみに制限" #: mod_muc/mod_muc_room.erl:2969 msgid "Make room moderated" -msgstr "チャットルームをモデレートする" +msgstr "チャットルームをモデレート化" #: mod_muc/mod_muc_room.erl:2972 msgid "Default users as participants" -msgstr "デフォルトのユーザーは参加者にする" +msgstr "デフォルトのユーザーは参加者" #: mod_muc/mod_muc_room.erl:2975 msgid "Allow users to change the subject" -msgstr "ユーザーによる件名の変更を許可する" +msgstr "ユーザーによる件名の変更を許可" #: mod_muc/mod_muc_room.erl:2978 msgid "Allow users to send private messages" -msgstr "ユーザーによるプライベートメッセージの送信を許可する" +msgstr "ユーザーによるプライベートメッセージの送信を許可" #: mod_muc/mod_muc_room.erl:2981 msgid "Allow users to query other users" -msgstr "ユーザーによる他のユーザーへの問い合わせを許可する" +msgstr "ユーザーによる他のユーザーへのクエリーを許可" #: mod_muc/mod_muc_room.erl:2984 msgid "Allow users to send invites" -msgstr "ユーザーによる招待を許可する" +msgstr "ユーザーによる招待を許可" #: mod_muc/mod_muc_room.erl:2987 msgid "Allow visitors to send status text in presence updates" -msgstr "ビジターがプレゼンス更新のステータス文を送信する事を許可する" +msgstr "ビジターによるプレゼンス更新のステータス文の送信を許可" #: mod_muc/mod_muc_room.erl:2990 msgid "Allow visitors to change nickname" -msgstr "ビジターがニックネームを変更する事を許可します" +msgstr "ビジターのニックネームの変更を許可" #: mod_muc/mod_muc_room.erl:2996 msgid "Make room captcha protected" -msgstr "チャットルームをキャプチャで保護します" +msgstr "チャットルームを CAPTCHA で保護" #: mod_muc/mod_muc_room.erl:3005 msgid "Enable logging" -msgstr "ロギングを有効にする" +msgstr "ロギングを有効" #: mod_muc/mod_muc_room.erl:3013 msgid "You need an x:data capable client to configure room" msgstr "" -"チャットルームを設定するにはにはクライアントが x:data をサポートする必要があ" -"ります" +"チャットルームを設定するにはクライアントが x:data をサポートする必要がありま" +"す" #: mod_muc/mod_muc_room.erl:3327 msgid "Number of occupants" -msgstr "居住者の数" +msgstr "在室者の数" #: mod_muc/mod_muc_room.erl:3383 msgid "private, " -msgstr "プライベート" +msgstr "プライベート、" #: mod_muc/mod_muc_room.erl:3466 msgid "~s invites you to the room ~s" @@ -983,7 +984,7 @@ msgstr "" #: mod_offline.erl:560 mod_offline_odbc.erl:408 msgid "~s's Offline Messages Queue" -msgstr "~s's オフラインメッセージキュー" +msgstr "~s' のオフラインメッセージキュー" #: mod_offline.erl:563 mod_offline_odbc.erl:411 mod_roster.erl:992 #: mod_roster_odbc.erl:1092 mod_shared_roster.erl:810 @@ -1020,11 +1021,11 @@ msgstr "選択した項目を削除" #: mod_offline.erl:645 mod_offline_odbc.erl:519 msgid "Offline Messages:" -msgstr "オフラインメッセージ" +msgstr "オフラインメッセージ:" #: mod_offline.erl:645 mod_offline_odbc.erl:519 msgid "Remove All Offline Messages" -msgstr "すべてのオフラインメッセージを削除します" +msgstr "すべてのオフラインメッセージを削除" #: mod_proxy65/mod_proxy65_service.erl:213 msgid "ejabberd SOCKS5 Bytestreams module" @@ -1040,11 +1041,11 @@ msgstr "ejabberd Publish-Subscribe module" #: mod_pubsub/mod_pubsub.erl:1496 mod_pubsub/mod_pubsub_odbc.erl:1311 msgid "PubSub subscriber request" -msgstr "PubSub 購読リクエスト" +msgstr "PubSub 購読者のリクエスト" #: mod_pubsub/mod_pubsub.erl:1498 mod_pubsub/mod_pubsub_odbc.erl:1313 msgid "Choose whether to approve this entity's subscription." -msgstr "このエントリを承認するかどうかを選択して下さい" +msgstr "このエントリを承認するかどうかを選択してください" #: mod_pubsub/mod_pubsub.erl:1504 mod_pubsub/mod_pubsub_odbc.erl:1319 msgid "Node ID" @@ -1052,31 +1053,31 @@ msgstr "ノードID" #: mod_pubsub/mod_pubsub.erl:1509 mod_pubsub/mod_pubsub_odbc.erl:1324 msgid "Subscriber Address" -msgstr "購読アドレス" +msgstr "購読者のアドレス" #: mod_pubsub/mod_pubsub.erl:1515 mod_pubsub/mod_pubsub_odbc.erl:1330 msgid "Allow this Jabber ID to subscribe to this pubsub node?" -msgstr "この Jabber ID をこの pubsubノードへ購読することを許可しますか?" +msgstr "この Jabber ID に、この pubsubノードの購読を許可しますか ?" #: mod_pubsub/mod_pubsub.erl:3387 mod_pubsub/mod_pubsub_odbc.erl:3229 msgid "Deliver payloads with event notifications" -msgstr "イベント通知と同時にペイロードを配送します" +msgstr "イベント通知と同時にペイロードを配送する" #: mod_pubsub/mod_pubsub.erl:3388 mod_pubsub/mod_pubsub_odbc.erl:3230 msgid "Deliver event notifications" -msgstr "イベント通知を配送します" +msgstr "イベント通知を配送する" #: mod_pubsub/mod_pubsub.erl:3389 mod_pubsub/mod_pubsub_odbc.erl:3231 msgid "Notify subscribers when the node configuration changes" -msgstr "ノード設定に変更があった時に購読者へ通知します" +msgstr "ノード設定に変更があった時に購読者へ通知する" #: mod_pubsub/mod_pubsub.erl:3390 mod_pubsub/mod_pubsub_odbc.erl:3232 msgid "Notify subscribers when the node is deleted" -msgstr "ノードが削除された時に購読者へ通知します" +msgstr "ノードが削除された時に購読者へ通知する" #: mod_pubsub/mod_pubsub.erl:3391 mod_pubsub/mod_pubsub_odbc.erl:3233 msgid "Notify subscribers when items are removed from the node" -msgstr "アイテムがノードから消された時に購読者へ通知します" +msgstr "アイテムがノードから消された時に購読者へ通知する" #: mod_pubsub/mod_pubsub.erl:3392 mod_pubsub/mod_pubsub_odbc.erl:3234 msgid "Persist items to storage" @@ -1084,11 +1085,11 @@ msgstr "アイテムをストレージに保存する" #: mod_pubsub/mod_pubsub.erl:3393 mod_pubsub/mod_pubsub_odbc.erl:3235 msgid "A friendly name for the node" -msgstr "ノードの為のフレンドリネーム" +msgstr "ノードのフレンドリネーム" #: mod_pubsub/mod_pubsub.erl:3394 mod_pubsub/mod_pubsub_odbc.erl:3236 msgid "Max # of items to persist" -msgstr "アイテムの最大保存数 #" +msgstr "アイテムの最大保存数" #: mod_pubsub/mod_pubsub.erl:3395 mod_pubsub/mod_pubsub_odbc.erl:3237 msgid "Whether to allow subscriptions" @@ -1108,7 +1109,7 @@ msgstr "公開モデルを指定する" #: mod_pubsub/mod_pubsub.erl:3402 mod_pubsub/mod_pubsub_odbc.erl:3244 msgid "Purge all items when the relevant publisher goes offline" -msgstr "公開者がオフラインになる時に、全てののアイテムを削除" +msgstr "公開者がオフラインになるときに、すべてのアイテムを削除" #: mod_pubsub/mod_pubsub.erl:3403 mod_pubsub/mod_pubsub_odbc.erl:3245 msgid "Specify the event message type" @@ -1116,7 +1117,7 @@ msgstr "イベントメッセージ種別を設定" #: mod_pubsub/mod_pubsub.erl:3405 mod_pubsub/mod_pubsub_odbc.erl:3247 msgid "Max payload size in bytes" -msgstr "最大ぺイロードサイズ(byte)" +msgstr "最大ぺイロードサイズ (byte)" #: mod_pubsub/mod_pubsub.erl:3406 mod_pubsub/mod_pubsub_odbc.erl:3248 msgid "When to send the last published item" @@ -1132,16 +1133,16 @@ msgstr "提携されたノードの集合です" #: mod_register.erl:191 msgid "The CAPTCHA verification has failed" -msgstr "キャプチャ検証は失敗しました" +msgstr "CAPTCHA 検証は失敗しました" #: mod_register.erl:218 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" -"登録を行うにはクライアントがx:dataとキャプチャをサポートする必要があります" +"登録を行うにはクライアントが x:data と CAPTCHA をサポートする必要があります" #: mod_register.erl:224 mod_register.erl:258 msgid "Choose a username and password to register with this server" -msgstr "サーバーに登録するユーザー名とパスワードを選択して下さい" +msgstr "サーバーに登録するユーザー名とパスワードを選択してください" #: mod_register.erl:228 mod_vcard.erl:358 mod_vcard_odbc.erl:336 #: web/ejabberd_web_admin.erl:1512 web/ejabberd_web_admin.erl:1569 @@ -1150,7 +1151,7 @@ msgstr "ユーザー" #: mod_register.erl:244 msgid "Unable to generate a CAPTCHA" -msgstr "キャプチャを生成出来ませんでした" +msgstr "CAPTCHA を生成できませんでした" #: mod_register.erl:309 mod_register.erl:354 msgid "The password is too weak" @@ -1164,7 +1165,7 @@ msgstr "早すぎるユーザーアカウント登録は許可されていませ #: web/ejabberd_web_admin.erl:1880 web/ejabberd_web_admin.erl:1891 #: web/ejabberd_web_admin.erl:2214 msgid "None" -msgstr "無し" +msgstr "なし" #: mod_roster.erl:950 mod_roster_odbc.erl:1050 msgid "Subscription" @@ -1202,7 +1203,7 @@ msgstr "不正なフォーマット" #: mod_roster.erl:1000 mod_roster_odbc.erl:1100 msgid "Add Jabber ID" -msgstr "Jabber ID の追加" +msgstr "Jabber ID を追加" #: mod_roster.erl:1099 mod_roster_odbc.erl:1199 msgid "Roster" @@ -1220,11 +1221,11 @@ msgstr "新規追加" #: mod_shared_roster.erl:879 msgid "Name:" -msgstr "名前: " +msgstr "名前:" #: mod_shared_roster.erl:884 msgid "Description:" -msgstr "詳細:" +msgstr "説明:" #: mod_shared_roster.erl:892 msgid "Members:" @@ -1328,7 +1329,7 @@ msgstr "検索結果: " #: mod_vcard_ldap.erl:458 msgid "Fill in fields to search for any matching Jabber User" -msgstr "項目を埋めて Jabber User を検索して下さい" +msgstr "項目を埋めて Jabber User を検索してください" #: web/ejabberd_web_admin.erl:189 web/ejabberd_web_admin.erl:199 #: web/ejabberd_web_admin.erl:215 web/ejabberd_web_admin.erl:225 @@ -1352,8 +1353,8 @@ msgid "~s access rule configuration" msgstr "~s アクセスルール設定" #: web/ejabberd_web_admin.erl:1031 -msgid "Virtual Hosts" -msgstr "ヴァーチャルホスト" +msgid "ejabberd virtual hosts" +msgstr "ejabberd ヴァーチャルホスト" #: web/ejabberd_web_admin.erl:1039 web/ejabberd_web_admin.erl:1046 msgid "Users" @@ -1377,15 +1378,15 @@ msgstr "去年" #: web/ejabberd_web_admin.erl:1088 msgid "All activity" -msgstr "全て" +msgstr "すべて" #: web/ejabberd_web_admin.erl:1090 msgid "Show Ordinary Table" -msgstr "Ordinaryテーブルを表示" +msgstr "Ordinary テーブルを表示" #: web/ejabberd_web_admin.erl:1092 msgid "Show Integral Table" -msgstr "Integralテーブルを表示" +msgstr "Integral テーブルを表示" #: web/ejabberd_web_admin.erl:1101 web/ejabberd_web_admin.erl:1933 msgid "Statistics" @@ -1436,7 +1437,7 @@ msgstr "外向き s2s サービス:" #: web/mod_register_web.erl:367 web/mod_register_web.erl:376 #: web/mod_register_web.erl:406 msgid "Change Password" -msgstr "パスワードの変更" +msgstr "パスワードを変更" #: web/ejabberd_web_admin.erl:1752 msgid "User " @@ -1453,7 +1454,7 @@ msgstr "パスワード" #: web/ejabberd_web_admin.erl:1822 msgid "No Data" -msgstr "データ無し" +msgstr "データなし" #: web/ejabberd_web_admin.erl:1900 msgid "Nodes" @@ -1514,13 +1515,13 @@ msgid "" "If you are using the ODBC module, you also need to backup your SQL database " "separately." msgstr "" -"これらのオプションは組み込みの Mnesiaデーターベースをバックアップのみを行うこ" -"とに注意して下さい。もしも ODBCモジュールを使用している場合は SQLデーターベー" -"スのバックアップを別に行う必要があります。" +"これらのオプションは組み込みの Mnesia データーベースのバックアップのみを行う" +"ことに注意してください。もし ODBC モジュールを使用している場合は、SQL デー" +"ターベースのバックアップを別に行う必要があります。" #: web/ejabberd_web_admin.erl:2036 msgid "Store binary backup:" -msgstr "バイナリバックアップの保存" +msgstr "バイナリバックアップを保存:" #: web/ejabberd_web_admin.erl:2040 web/ejabberd_web_admin.erl:2047 #: web/ejabberd_web_admin.erl:2055 web/ejabberd_web_admin.erl:2062 @@ -1532,33 +1533,34 @@ msgstr "OK" #: web/ejabberd_web_admin.erl:2043 msgid "Restore binary backup immediately:" -msgstr "直ちにバイナリバックアップからリストア" +msgstr "直ちにバイナリバックアップからリストア:" #: web/ejabberd_web_admin.erl:2051 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" -msgstr "ejabberd の再起動時にバイナリバックアップからリストア" +msgstr "ejabberd の再起動時にバイナリバックアップからリストア (メモリ少):" #: web/ejabberd_web_admin.erl:2058 msgid "Store plain text backup:" -msgstr "プレーンテキストバックアップの保存" +msgstr "プレーンテキストバックアップを保存:" #: web/ejabberd_web_admin.erl:2065 msgid "Restore plain text backup immediately:" -msgstr "直ちにプレーンテキストバックアップからリストア" +msgstr "直ちにプレーンテキストバックアップからリストア:" #: web/ejabberd_web_admin.erl:2072 msgid "Import users data from a PIEFXIS file (XEP-0227):" -msgstr "ユーザーデータを PIEFXISファイルからインポート(XEP-0227):" +msgstr "ユーザーデータを PIEFXIS ファイルからインポート (XEP-0227):" #: web/ejabberd_web_admin.erl:2079 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -"サーバーにある全てのユーザーデータをPIEFXISファイルにエクスポート(XEP-0227):" +"サーバーにあるすべてのユーザーデータを PIEFXIS ファイルにエクスポート " +"(XEP-0227):" #: web/ejabberd_web_admin.erl:2086 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" -msgstr "ホストのユーザーデータをPIEFXISファイルにエクスポート(XEP-0227):" +msgstr "ホストのユーザーデータを PIEFXIS ファイルにエクスポート (XEP-0227):" #: web/ejabberd_web_admin.erl:2094 msgid "Import user data from jabberd14 spool file:" @@ -1582,7 +1584,7 @@ msgstr "~p の統計" #: web/ejabberd_web_admin.erl:2181 msgid "Uptime:" -msgstr "起動時間" +msgstr "起動時間:" #: web/ejabberd_web_admin.erl:2184 msgid "CPU Time:" @@ -1614,7 +1616,7 @@ msgstr "更新計画" #: web/ejabberd_web_admin.erl:2250 msgid "Modified modules" -msgstr "モジュールを変更しました" +msgstr "変更されたモジュール" #: web/ejabberd_web_admin.erl:2251 msgid "Update script" @@ -1658,7 +1660,7 @@ msgstr "開始" #: web/mod_register_web.erl:103 msgid "Your Jabber account was successfully created." -msgstr "Jabberアカウントの作成に成功しました。" +msgstr "Jabber アカウントの作成に成功しました。" #: web/mod_register_web.erl:106 msgid "There was an error creating the account: " @@ -1666,7 +1668,7 @@ msgstr "アカウントの作成中にエラーが発生しました: " #: web/mod_register_web.erl:114 msgid "Your Jabber account was successfully deleted." -msgstr "Jabberアカウントの削除に成功しました。" +msgstr "Jabber アカウントの削除に成功しました。" #: web/mod_register_web.erl:117 msgid "There was an error deleting the account: " @@ -1674,7 +1676,7 @@ msgstr "アカウントの削除中にエラーが発生しました: " #: web/mod_register_web.erl:127 msgid "The password of your Jabber account was successfully changed." -msgstr "Jabberアカウントのパスワード変更に成功しました。" +msgstr "Jabber アカウントのパスワード変更に成功しました。" #: web/mod_register_web.erl:130 msgid "There was an error changing the password: " @@ -1682,17 +1684,17 @@ msgstr "パスワードの変更中にエラーが発生しました: " #: web/mod_register_web.erl:162 web/mod_register_web.erl:171 msgid "Jabber Account Registration" -msgstr "Jabberアカウント登録" +msgstr "Jabber アカウント登録" #: web/mod_register_web.erl:173 web/mod_register_web.erl:191 #: web/mod_register_web.erl:200 msgid "Register a Jabber account" -msgstr "Jabberアカウントを登録" +msgstr "Jabber アカウントを登録" #: web/mod_register_web.erl:175 web/mod_register_web.erl:488 #: web/mod_register_web.erl:497 msgid "Unregister a Jabber account" -msgstr "Jabberアカウントの登録解除" +msgstr "Jabber アカウントを削除" #: web/mod_register_web.erl:202 msgid "" @@ -1700,9 +1702,9 @@ msgid "" "(Jabber IDentifier) will be of the form: username@server. Please read " "carefully the instructions to fill correctly the fields." msgstr "" -"ここはJabberサーバーにアカウント作成を行うページです。あなたのJID(JabberID)" -"は username@server の様な形式に成ります。注意事項通り、正しく項目に記入して下" -"さい。" +"ここは Jabber サーバーにアカウントを作成するページです。あなたの JID " +"(JabberID) は username@server のような形式になります。注意事項どおり、正しく" +"項目を記入してください。" #: web/mod_register_web.erl:211 web/mod_register_web.erl:381 #: web/mod_register_web.erl:504 @@ -1716,7 +1718,7 @@ msgstr "" #: web/mod_register_web.erl:217 msgid "Characters not allowed:" -msgstr "許可されていない文字:" +msgstr "使用できない文字:" #: web/mod_register_web.erl:221 web/mod_register_web.erl:386 #: web/mod_register_web.erl:509 @@ -1728,21 +1730,22 @@ msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -"パスワードは誰にも教えないようにして下さい。Jabberサーバーの管理者があなたに" -"パスワードを尋ねることはありません。" +"パスワードは誰にも教えないようにしてください。Jabber サーバーの管理者があなた" +"にパスワードを尋ねることはありません。" #: web/mod_register_web.erl:233 msgid "You can later change your password using a Jabber client." msgstr "" -"あなたは後からJabberクライアントを使用してパスワードを変更する事が出来ます。" +"あなたは後から Jabber クライアントを使用してパスワードを変更することができま" +"す。" #: web/mod_register_web.erl:234 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -"Jabberクライアントはコンピューターにあなたのパスワード記憶出来ます。この機能" -"を使用する場合コンピューターが安全であることを確認して下さい。" +"Jabber クライアントはコンピューターにあなたのパスワードを記憶できます。この機能" +"を使用する場合、コンピューターが安全であることを確認してください。" #: web/mod_register_web.erl:236 msgid "" @@ -1750,13 +1753,13 @@ msgid "" "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -"パスワードは記憶するか、紙に書いて安全な場所に保管して下さい。もしあなたがパ" -"スワードを忘れてしまった場合、Jabberではパスワードのリカバリを自動的に行うこ" -"とは出来ません。" +"パスワードは記憶するか、紙に書いて安全な場所に保管してください。もしあなたが" +"パスワードを忘れてしまった場合、Jabber ではパスワードのリカバリを自動的に行う" +"ことはできません。" #: web/mod_register_web.erl:241 web/mod_register_web.erl:401 msgid "Password Verification:" -msgstr "パスワード(確認):" +msgstr "パスワード (確認):" #: web/mod_register_web.erl:249 msgid "Register" @@ -1772,11 +1775,11 @@ msgstr "新しいパスワード:" #: web/mod_register_web.erl:499 msgid "This page allows to unregister a Jabber account in this Jabber server." -msgstr "ここはサーバーのJabberアカウントの登録削除を行うページです。" +msgstr "ここはサーバーの Jabber アカウントの削除を行うページです。" #: web/mod_register_web.erl:519 msgid "Unregister" -msgstr "登録解除" +msgstr "削除" #~ msgid "Captcha test failed" #~ msgstr "キャプチャのテストに失敗しました" @@ -1787,6 +1790,9 @@ msgstr "登録解除" #~ msgid "(Raw)" #~ msgstr "(Raw)" +msgid "Virtual Hosts" +msgstr "ヴァーチャルホスト" + #~ msgid "Specified nickname is already registered" #~ msgstr "指定されたニックネームは既に登録されています" From dac1f328d7a13603966939a14025dbb278000631 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 7 Apr 2011 12:06:31 +0200 Subject: [PATCH 16/47] Clarify {iqdisc, no_queue} --- doc/guide.tex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index 72bb13247..dee622da2 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -2622,15 +2622,16 @@ The syntax is: Possible \term{Value} are: \begin{description} \titem{no\_queue} All queries of a namespace with this processing discipline are - processed immediately. This also means that no other packets can be processed + processed directly. This means that the XMPP connection that sends this IQ query gets blocked: + no other packets can be processed until this one has been completely processed. Hence this discipline is not recommended if the processing of a query can take a relatively long time. \titem{one\_queue} In this case a separate queue is created for the processing of IQ queries of a namespace with this discipline. In addition, the processing of this queue is done in parallel with that of other packets. This discipline is most recommended. - \titem{\{queues, N\}} N separate queues are created to process the - queries. The queries are thus process in parallel, but in a +\titem{\{queues, N\}} N separate queues are created to process the + queries. The queries are thus processed in parallel, but in a controlled way. \titem{parallel} For every packet with this discipline a separate Erlang process is spawned. Consequently, all these packets are processed in parallel. From aded9663703c7d9ab893d90c6b56bd8b7da7b8e6 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 7 Apr 2011 12:08:31 +0200 Subject: [PATCH 17/47] mod_ping uses iqdisc no_queue by default (thanks to Chris Moos)(EJAB-1435) --- src/mod_ping.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_ping.erl b/src/mod_ping.erl index c5d96d88d..a1e6b2664 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -95,7 +95,7 @@ init([Host, Opts]) -> SendPings = gen_mod:get_opt(send_pings, Opts, ?DEFAULT_SEND_PINGS), PingInterval = gen_mod:get_opt(ping_interval, Opts, ?DEFAULT_PING_INTERVAL), TimeoutAction = gen_mod:get_opt(timeout_action, Opts, none), - IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), + IQDisc = gen_mod:get_opt(iqdisc, Opts, no_queue), mod_disco:register_feature(Host, ?NS_PING), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PING, ?MODULE, iq_ping, IQDisc), From 449e56ed5241adc8e206d45b66515eca38d8df36 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 7 Apr 2011 12:54:39 +0200 Subject: [PATCH 18/47] Send jid attribute when occupant is banned (EJAB-1432) --- src/mod_muc/mod_muc_room.erl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 30e8897bb..894abd535 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -2667,14 +2667,21 @@ send_kickban_presence(JID, Reason, Code, NewAffiliation, StateData) -> end, LJIDs). send_kickban_presence1(UJID, Reason, Code, Affiliation, StateData) -> - {ok, #user{jid = _RealJID, + {ok, #user{jid = RealJID, nick = Nick}} = ?DICT:find(jlib:jid_tolower(UJID), StateData#state.users), SAffiliation = affiliation_to_list(Affiliation), + BannedJIDString = jlib:jid_to_string(RealJID), lists:foreach( fun({_LJID, Info}) -> + JidAttrList = case (Info#user.role == moderator) orelse + ((StateData#state.config)#config.anonymous + == false) of + true -> [{"jid", BannedJIDString}]; + false -> [] + end, ItemAttrs = [{"affiliation", SAffiliation}, - {"role", "none"}], + {"role", "none"}] ++ JidAttrList, ItemEls = case Reason of "" -> []; From 7d7621c67c5b599c8a2b0b01f2719816db539d82 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 11 Apr 2011 19:58:25 +0200 Subject: [PATCH 19/47] Support more captcha_host value formats (EJAB-1418) --- doc/guide.tex | 13 +++++++------ src/ejabberd_captcha.erl | 10 +++++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index dee622da2..5c157aa37 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -1634,13 +1634,13 @@ The configurable options are: Full path to a script that generates the image. The default value is an empty string: \term{""} \titem{\{captcha\_host, ProtocolHostPort\}} - Host part of the URL sent to the user, - and the port number where ejabberd listens for CAPTCHA requests. - The URL sent to the user is formed by: \term{http://Host:Port/captcha/} - The default value is: the first hostname configured, and port 5280. - If the port number you specify does not match exactly an ejabberd listener + ProtocolHostPort is a string with the host, and optionally the Protocol and Port number. + It must identify where ejabberd listens for CAPTCHA requests. + The URL sent to the user is formed by: \term{Protocol://Host:Port/captcha/} + The default value is: protocol \term{http}, the first hostname configured, and port \term{80}. + If you specify a port number that does not match exactly an ejabberd listener (because you are using a reverse proxy or other port-forwarding tool), - then specify also the transfer protocol, as seen in the example below. + then you must specify the transfer protocol, as seen in the example below. \end{description} Additionally, an \term{ejabberd\_http} listener must be enabled with the \term{captcha} option. @@ -1653,6 +1653,7 @@ Example configuration: {captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}. {captcha_host, "example.org:5280"}. %% {captcha_host, "https://example.org:443"}. +%% {captcha_host, "http://example.com"}. {listen, [ diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 797a6152d..91e14c735 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -407,13 +407,17 @@ get_prog_name() -> get_url(Str) -> CaptchaHost = ejabberd_config:get_local_option(captcha_host), case string:tokens(CaptchaHost, ":") of - [TransferProt, Host, PortString] -> - TransferProt ++ ":" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str; + [Host] -> + "http://" ++ Host ++ "/captcha/" ++ Str; + ["http"++_ = TransferProt, Host] -> + TransferProt ++ ":" ++ Host ++ "/captcha/" ++ Str; [Host, PortString] -> TransferProt = atom_to_list(get_transfer_protocol(PortString)), TransferProt ++ "://" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str; + [TransferProt, Host, PortString] -> + TransferProt ++ ":" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str; _ -> - "http://" ++ ?MYNAME ++ ":5280/captcha/" ++ Str + "http://" ++ ?MYNAME ++ "/captcha/" ++ Str end. get_transfer_protocol(PortString) -> From 05e3893f60b82da54d001782cd3d7eec6b0612f1 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 11 Apr 2011 21:27:19 +0200 Subject: [PATCH 20/47] If extauth script crashes, ejabberd should restart it (EJAB-1428) --- src/extauth.erl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/extauth.erl b/src/extauth.erl index 3b2e7db64..f49392983 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -45,11 +45,18 @@ start(Host, ExtPrg) -> lists:foreach( fun(This) -> - spawn(?MODULE, init, [get_process_name(Host, This), ExtPrg]) + start_instance(get_process_name(Host, This), ExtPrg) end, lists:seq(0, get_instances(Host)-1) ). +start_instance(ProcessName, ExtPrg) -> + spawn(?MODULE, init, [ProcessName, ExtPrg]). + +restart_instance(ProcessName, ExtPrg) -> + unregister(ProcessName), + start_instance(ProcessName, ExtPrg). + init(ProcessName, ExtPrg) -> register(ProcessName, self()), process_flag(trap_exit,true), @@ -125,8 +132,7 @@ loop(Port, Timeout, ProcessName, ExtPrg) -> Timeout -> ?ERROR_MSG("extauth call '~p' didn't receive response", [Msg]), Caller ! {eauth, false}, - unregister(ProcessName), - Pid = spawn(?MODULE, init, [ProcessName, ExtPrg]), + Pid = restart_instance(ProcessName, ExtPrg), flush_buffer_and_forward_messages(Pid), exit(port_terminated) end; @@ -137,7 +143,9 @@ loop(Port, Timeout, ProcessName, ExtPrg) -> exit(normal) end; {'EXIT', Port, Reason} -> - ?CRITICAL_MSG("~p ~n", [Reason]), + ?CRITICAL_MSG("extauth script has exitted abruptly with reason '~p'", [Reason]), + Pid = restart_instance(ProcessName, ExtPrg), + flush_buffer_and_forward_messages(Pid), exit(port_terminated) end. From f59a979f7ca135619a77fd9b8a2dc2062534fa27 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 12 Apr 2011 23:13:46 +0200 Subject: [PATCH 21/47] Support as read-only HTTP method not only GET, also HEAD --- src/web/ejabberd_web_admin.erl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl index 90e301401..f3809c15e 100644 --- a/src/web/ejabberd_web_admin.erl +++ b/src/web/ejabberd_web_admin.erl @@ -64,11 +64,15 @@ get_acl_rule(["additions.js"],_) -> {"localhost", [all]}; get_acl_rule(["vhosts"],_) -> {"localhost", [all]}; %% The pages of a vhost are only accesible if the user is admin of that vhost: -get_acl_rule(["server", VHost | _RPath], 'GET') -> {VHost, [configure, webadmin_view]}; +get_acl_rule(["server", VHost | _RPath], Method) + when Method=:='GET' orelse Method=:='HEAD' -> + {VHost, [configure, webadmin_view]}; get_acl_rule(["server", VHost | _RPath], 'POST') -> {VHost, [configure]}; %% Default rule: only global admins can access any other random page -get_acl_rule(_RPath, 'GET') -> {global, [configure, webadmin_view]}; +get_acl_rule(_RPath, Method) + when Method=:='GET' orelse Method=:='HEAD' -> + {global, [configure, webadmin_view]}; get_acl_rule(_RPath, 'POST') -> {global, [configure]}. is_acl_match(Host, Rules, Jid) -> From 70bf5b4edadab95c50f377b859752f41d32e05e3 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 12 Apr 2011 23:31:08 +0200 Subject: [PATCH 22/47] The responses to HEAD must have empty Body --- src/web/ejabberd_http.erl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl index ef370eb99..ea6851902 100644 --- a/src/web/ejabberd_http.erl +++ b/src/web/ejabberd_http.erl @@ -557,7 +557,13 @@ make_xhtml_output(State, Status, Headers, XHTML) -> end, HeadersOut), SL = [Version, integer_to_list(Status), " ", code_to_phrase(Status), "\r\n"], - [SL, H, "\r\n", Data]. + + Data2 = case State#state.request_method of + 'HEAD' -> ""; + _ -> Data + end, + + [SL, H, "\r\n", Data2]. make_text_output(State, Status, Headers, Text) when is_list(Text) -> make_text_output(State, Status, Headers, list_to_binary(Text)); @@ -594,7 +600,13 @@ make_text_output(State, Status, Headers, Data) when is_binary(Data) -> end, HeadersOut), SL = [Version, integer_to_list(Status), " ", code_to_phrase(Status), "\r\n"], - [SL, H, "\r\n", Data]. + + Data2 = case State#state.request_method of + 'HEAD' -> ""; + _ -> Data + end, + + [SL, H, "\r\n", Data2]. parse_lang(Langs) -> From 4f1ececbd17cdc6ff19a42d5c7cacb32744800c7 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 14 Apr 2011 23:11:37 +0200 Subject: [PATCH 23/47] Try to improve support for roster_version in MSSQL (EJAB-1437) --- src/odbc/mssql2000.sql | 34 ++++++++++++++++++++++++++++++++++ src/odbc/mssql2005.sql | 34 ++++++++++++++++++++++++++++++++++ src/odbc/odbc_queries.erl | 16 ++++++++++++---- 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/odbc/mssql2000.sql b/src/odbc/mssql2000.sql index 151d474a5..d4a70989d 100644 --- a/src/odbc/mssql2000.sql +++ b/src/odbc/mssql2000.sql @@ -597,6 +597,40 @@ BEGIN END GO +/******************************************************************/ +/****** Object: StoredProcedure [dbo].[set_roster_version] **/ +/** Update users roster_version **/ +/******************************************************************/ +CREATE PROCEDURE [dbo].[set_roster_version] + @Username varchar(200), + @Version varchar(50) +AS +BEGIN + IF EXISTS (SELECT username FROM roster_version WITH (NOLOCK) WHERE username=@Username) + BEGIN + UPDATE roster_version SET username=@Username, version=@Version WHERE username=@Username; + END + ELSE + BEGIN + INSERT INTO roster_version (username, version) VALUES (@Username, @Version); + END +END +GO + +/******************************************************************/ +/****** Object: StoredProcedure [dbo].[get_roster_version] **/ +/** Retrive the user roster_version **/ +/******************************************************************/ +CREATE PROCEDURE [dbo].[get_roster_version] + @Username varchar(200) +AS +BEGIN + SELECT roster_version.version as version + FROM roster_version WITH (NOLOCK) + WHERE username=@Username; +END +GO + /***************************************************************/ /****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/ /** Delete messages older that 3 days from spool **/ diff --git a/src/odbc/mssql2005.sql b/src/odbc/mssql2005.sql index 8420b7690..911207078 100644 --- a/src/odbc/mssql2005.sql +++ b/src/odbc/mssql2005.sql @@ -918,6 +918,40 @@ BEGIN END GO +/******************************************************************/ +/****** Object: StoredProcedure [dbo].[set_roster_version] **/ +/** Update users roster_version **/ +/******************************************************************/ +CREATE PROCEDURE [dbo].[set_roster_version] + @Username varchar(200), + @Version varchar(8000) +AS +BEGIN + IF EXISTS (SELECT username FROM roster_version WITH (NOLOCK) WHERE username=@Username) + BEGIN + UPDATE roster_version SET username=@Username, version=@Version WHERE username=@Username; + END + ELSE + BEGIN + INSERT INTO roster_version (username, version) VALUES (@Username, @Version); + END +END +GO + +/******************************************************************/ +/****** Object: StoredProcedure [dbo].[get_roster_version] **/ +/** Retrive the user roster_version **/ +/******************************************************************/ +CREATE PROCEDURE [dbo].[get_roster_version] + @Username varchar(200) +AS +BEGIN + SELECT roster_version.version as version + FROM roster_version WITH (NOLOCK) + WHERE username=@Username; +END +GO + /***************************************************************/ /****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/ /** Delete messages older that 3 days from spool **/ diff --git a/src/odbc/odbc_queries.erl b/src/odbc/odbc_queries.erl index 3e3a29422..b614fd790 100644 --- a/src/odbc/odbc_queries.erl +++ b/src/odbc/odbc_queries.erl @@ -90,6 +90,8 @@ -define(generic, true). -endif. +-include("ejabberd.hrl"). + %% Almost a copy of string:join/2. %% We use this version because string:join/2 is relatively %% new function (introduced in R12B-0). @@ -882,8 +884,14 @@ count_records_where(LServer, Table, WhereClause) -> ["select count(*) from ", Table, " with (nolock) ", WhereClause]). get_roster_version(LServer, LUser) -> - ejabberd_odbc:sql_query(LServer, - ["select version from dbo.roster_version with (nolock) where username = '", LUser, "'"]). -set_roster_version(LUser, Version) -> - update_t("dbo.roster_version", ["username", "version"], [LUser, Version], ["username = '", LUser, "'"]). + ejabberd_odbc:sql_query( + LServer, + ["EXECUTE dbo.get_roster_version '", LUser, "'"]). + +set_roster_version(Username, Version) -> + %% This function doesn't know the vhost, so we hope it's the first one defined: + LServer = ?MYNAME, + ejabberd_odbc:sql_query( + LServer, + ["EXECUTE dbo.set_roster_version '", Username, "', '", Version, "'"]). -endif. From cf6264f5071369452dfb319642dc0557b3e4c407 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 16 Feb 2011 19:14:39 +0900 Subject: [PATCH 24/47] CAPTCHA whitelist support --- src/mod_muc/mod_muc_room.erl | 47 +++++++++++++++++++++++++++++++++++- src/mod_muc/mod_muc_room.hrl | 1 + 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 894abd535..9d275d496 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -1693,7 +1693,24 @@ check_captcha(Affiliation, From, StateData) -> {ok, passed} -> true; _ -> - captcha_required + WList = (StateData#state.config)#config.captcha_whitelist, + #jid{luser = U, lserver = S, lresource = R} = From, + case ?SETS:is_element({U, S, R}, WList) of + true -> + true; + false -> + case ?SETS:is_element({U, S, ""}, WList) of + true -> + true; + false -> + case ?SETS:is_element({"", S, ""}, WList) of + true -> + true; + false -> + captcha_required + end + end + end end; _ -> true @@ -2882,6 +2899,13 @@ is_password_settings_correct(XEl, StateData) -> -define(PRIVATEXFIELD(Label, Var, Val), ?XFIELD("text-private", Label, Var, Val)). +-define(JIDMULTIXFIELD(Label, Var, JIDList), + {xmlelement, "field", [{"type", "jid-multi"}, + {"label", translate:translate(Lang, Label)}, + {"var", Var}], + [{xmlelement, "value", [], [{xmlcdata, jlib:jid_to_string(JID)}]} + || JID <- JIDList]}). + get_default_room_maxusers(RoomState) -> DefRoomOpts = gen_mod:get_module_opt(RoomState#state.server_host, mod_muc, default_room_options, []), RoomState2 = set_opts(DefRoomOpts, RoomState), @@ -3002,6 +3026,9 @@ get_config(Lang, StateData, From) -> Config#config.captcha_protected)]; false -> [] end ++ + [?JIDMULTIXFIELD("Exclude Jabber IDs from CAPTCHA challenge", + "muc#roomconfig_captcha_whitelist", + ?SETS:to_list(Config#config.captcha_whitelist))] ++ case mod_muc_log:check_access_log( StateData#state.server_host, From) of allow -> @@ -3071,6 +3098,18 @@ set_config(XEl, StateData) -> -define(SET_STRING_XOPT(Opt, Val), set_xoption(Opts, Config#config{Opt = Val})). +-define(SET_JIDMULTI_XOPT(Opt, Vals), + begin + Set = lists:foldl( + fun({U, S, R}, Set1) -> + ?SETS:add_element({U, S, R}, Set1); + (#jid{luser = U, lserver = S, lresource = R}, Set1) -> + ?SETS:add_element({U, S, R}, Set1); + (_, Set1) -> + Set1 + end, ?SETS:empty(), Vals), + set_xoption(Opts, Config#config{Opt = Set}) + end). set_xoption([], Config) -> Config; @@ -3128,6 +3167,9 @@ set_xoption([{"muc#roomconfig_maxusers", [Val]} | Opts], Config) -> end; set_xoption([{"muc#roomconfig_enablelogging", [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(logging, Val); +set_xoption([{"muc#roomconfig_captcha_whitelist", Vals} | Opts], Config) -> + JIDs = [jlib:string_to_jid(Val) || Val <- Vals], + ?SET_JIDMULTI_XOPT(captcha_whitelist, JIDs); set_xoption([{"FORM_TYPE", _} | Opts], Config) -> %% Ignore our FORM_TYPE set_xoption(Opts, Config); @@ -3197,6 +3239,7 @@ set_opts([{Opt, Val} | Opts], StateData) -> password -> StateData#state{config = (StateData#state.config)#config{password = Val}}; anonymous -> StateData#state{config = (StateData#state.config)#config{anonymous = Val}}; logging -> StateData#state{config = (StateData#state.config)#config{logging = Val}}; + captcha_whitelist -> StateData#state{config = (StateData#state.config)#config{captcha_whitelist = ?SETS:from_list(Val)}}; max_users -> ServiceMaxUsers = get_service_max_users(StateData), MaxUsers = if @@ -3241,6 +3284,8 @@ make_opts(StateData) -> ?MAKE_CONFIG_OPT(anonymous), ?MAKE_CONFIG_OPT(logging), ?MAKE_CONFIG_OPT(max_users), + {captcha_whitelist, + ?SETS:to_list((StateData#state.config)#config.captcha_whitelist)}, {affiliations, ?DICT:to_list(StateData#state.affiliations)}, {subject, StateData#state.subject}, {subject_author, StateData#state.subject_author} diff --git a/src/mod_muc/mod_muc_room.hrl b/src/mod_muc/mod_muc_room.hrl index eb5060e43..4779f8e6b 100644 --- a/src/mod_muc/mod_muc_room.hrl +++ b/src/mod_muc/mod_muc_room.hrl @@ -46,6 +46,7 @@ anonymous = true, max_users = ?MAX_USERS_DEFAULT, logging = false + captcha_whitelist = ?SETS:empty() }). -record(user, {jid, From 252ee6228b3cc653b46301d3a00a817251fa6643 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 18 Apr 2011 15:50:24 +1000 Subject: [PATCH 25/47] Fix syntax error --- src/mod_muc/mod_muc_room.hrl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_muc/mod_muc_room.hrl b/src/mod_muc/mod_muc_room.hrl index 4779f8e6b..192ecf845 100644 --- a/src/mod_muc/mod_muc_room.hrl +++ b/src/mod_muc/mod_muc_room.hrl @@ -45,7 +45,7 @@ password = "", anonymous = true, max_users = ?MAX_USERS_DEFAULT, - logging = false + logging = false, captcha_whitelist = ?SETS:empty() }). From 07cf6f09b8d12f1c6e3ba916c37ad93b181fa921 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 14 Apr 2011 18:03:02 +1000 Subject: [PATCH 26/47] Implement CAPTCHA limit --- src/ejabberd_captcha.erl | 129 +++++++++++++++++++++++++++-------- src/ejabberd_config.erl | 2 + src/mod_muc/mod_muc_room.erl | 17 +++-- src/mod_register.erl | 9 ++- src/web/mod_register_web.erl | 39 ++++++----- 5 files changed, 145 insertions(+), 51 deletions(-) diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 91e14c735..428346aba 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -27,7 +27,7 @@ -module(ejabberd_captcha). -behaviour(gen_server). - +-compile(export_all). %% API -export([start_link/0]). @@ -37,7 +37,7 @@ -export([create_captcha/6, build_captcha_html/2, check_captcha/2, process_reply/1, process/2, is_feature_available/0, - create_captcha_x/4, create_captcha_x/5]). + create_captcha_x/5, create_captcha_x/6]). -include("jlib.hrl"). -include("ejabberd.hrl"). @@ -49,8 +49,9 @@ -define(CAPTCHA_TEXT(Lang), translate:translate(Lang, "Enter the text you see")). -define(CAPTCHA_LIFETIME, 120000). % two minutes +-define(LIMIT_PERIOD, 60*1000*1000). % one minute --record(state, {}). +-record(state, {limits = treap:empty()}). -record(captcha, {id, pid, key, tref, args}). -define(T(S), @@ -72,11 +73,12 @@ start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). -create_captcha(Id, SID, From, To, Lang, Args) - when is_list(Id), is_list(Lang), is_list(SID), +create_captcha(SID, From, To, Lang, Limiter, Args) + when is_list(Lang), is_list(SID), is_record(From, jid), is_record(To, jid) -> - case create_image() of + case create_image(Limiter) of {ok, Type, Key, Image} -> + Id = randoms:get_string(), B64Image = jlib:encode_base64(binary_to_list(Image)), JID = jlib:jid_to_string(From), CID = "sha1+" ++ sha:sha(Image) ++ "@bob.xmpp.org", @@ -106,19 +108,19 @@ create_captcha(Id, SID, From, To, Lang, Args) case ?T(mnesia:write(#captcha{id=Id, pid=self(), key=Key, tref=Tref, args=Args})) of ok -> - {ok, [Body, OOB, Captcha, Data]}; - _Err -> - error + {ok, Id, [Body, OOB, Captcha, Data]}; + Err -> + {error, Err} end; - _Err -> - error + Err -> + Err end. -create_captcha_x(SID, To, Lang, HeadEls) -> - create_captcha_x(SID, To, Lang, HeadEls, []). +create_captcha_x(SID, To, Lang, Limiter, HeadEls) -> + create_captcha_x(SID, To, Lang, Limiter, HeadEls, []). -create_captcha_x(SID, To, Lang, HeadEls, TailEls) -> - case create_image() of +create_captcha_x(SID, To, Lang, Limiter, HeadEls, TailEls) -> + case create_image(Limiter) of {ok, Type, Key, Image} -> Id = randoms:get_string(), B64Image = jlib:encode_base64(binary_to_list(Image)), @@ -156,11 +158,11 @@ create_captcha_x(SID, To, Lang, HeadEls, TailEls) -> case ?T(mnesia:write(#captcha{id=Id, key=Key, tref=Tref})) of ok -> {ok, [Captcha, Data]}; - _Err -> - error + Err -> + {error, Err} end; - _ -> - error + Err -> + Err end. %% @spec (Id::string(), Lang::string()) -> {FormEl, {ImgEl, TextEl, IdEl, KeyEl}} | captcha_not_found @@ -275,16 +277,19 @@ process(_Handlers, #request{method='GET', lang=Lang, path=[_, Id]}) -> ejabberd_web:error(not_found) end; -process(_Handlers, #request{method='GET', path=[_, Id, "image"]}) -> +process(_Handlers, #request{method='GET', path=[_, Id, "image"], ip = IP}) -> + {Addr, _Port} = IP, case mnesia:dirty_read(captcha, Id) of [#captcha{key=Key}] -> - case create_image(Key) of + case create_image(Addr, Key) of {ok, Type, _, Img} -> {200, [{"Content-Type", Type}, {"Cache-Control", "no-cache"}, {"Last-Modified", httpd_util:rfc1123_date()}], Img}; + {error, limit} -> + ejabberd_web:error(not_allowed); _ -> ejabberd_web:error(not_found) end; @@ -323,6 +328,20 @@ init([]) -> check_captcha_setup(), {ok, #state{}}. +handle_call({is_limited, Limiter, RateLimit}, _From, State) -> + NowPriority = now_priority(), + CleanPriority = NowPriority + ?LIMIT_PERIOD, + Limits = clean_treap(State#state.limits, CleanPriority), + case treap:lookup(Limiter, Limits) of + {ok, _, Rate} when Rate >= RateLimit -> + {reply, true, State#state{limits = Limits}}; + {ok, Priority, Rate} -> + NewLimits = treap:insert(Limiter, Priority, Rate+1, Limits), + {reply, false, State#state{limits = NewLimits}}; + _ -> + NewLimits = treap:insert(Limiter, NowPriority, 1, Limits), + {reply, false, State#state{limits = NewLimits}} + end; handle_call(_Request, _From, State) -> {reply, bad_request, State}. @@ -364,11 +383,22 @@ code_change(_OldVsn, State, _Extra) -> %% Reason = atom() %%-------------------------------------------------------------------- create_image() -> + create_image(undefined). + +create_image(Limiter) -> %% Six numbers from 1 to 9. Key = string:substr(randoms:get_string(), 1, 6), - create_image(Key). + create_image(Limiter, Key). -create_image(Key) -> +create_image(Limiter, Key) -> + case is_limited(Limiter) of + true -> + {error, limit}; + false -> + do_create_image(Key) + end. + +do_create_image(Key) -> FileName = get_prog_name(), Cmd = lists:flatten(io_lib:format("~s ~s", [FileName, Key])), case cmd(Cmd) of @@ -455,6 +485,25 @@ get_captcha_transfer_protocol([{{_Port, _Ip, tcp}, ejabberd_http, Opts} get_captcha_transfer_protocol([_ | Listeners]) -> get_captcha_transfer_protocol(Listeners). +is_limited(undefined) -> + false; +is_limited(Limiter) -> + case ejabberd_config:get_local_option(captcha_limit) of + Int when is_integer(Int), Int > 0 -> + case catch gen_server:call(?MODULE, {is_limited, Limiter, Int}, + 5000) of + true -> + true; + false -> + false; + Err -> + ?ERROR_MSG("Call failed: ~p", [Err]), + false + end; + _ -> + false + end. + %%-------------------------------------------------------------------- %% Function: cmd(Cmd) -> Data | {error, Reason} %% Cmd = string() @@ -514,17 +563,41 @@ is_feature_available() -> case is_feature_enabled() of false -> false; true -> - case create_image() of - {ok, _, _, _} -> true; - _Error -> false - end + %% Do not generate image in order to avoid CAPTCHA DoS + %% case create_image() of + %% {ok, _, _, _} -> true; + %% _Error -> false + %% end + true end. check_captcha_setup() -> - case is_feature_enabled() andalso not is_feature_available() of + AbleToGenerateCaptcha = case create_image() of + {ok, _, _, _} -> true; + _Error -> false + end, + case is_feature_enabled() andalso not AbleToGenerateCaptcha of true -> ?CRITICAL_MSG("Captcha is enabled in the option captcha_cmd, " "but it can't generate images.", []); false -> ok end. + +clean_treap(Treap, CleanPriority) -> + case treap:is_empty(Treap) of + true -> + Treap; + false -> + {_Key, Priority, _Value} = treap:get_root(Treap), + if + Priority > CleanPriority -> + clean_treap(treap:delete_root(Treap), CleanPriority); + true -> + Treap + end + end. + +now_priority() -> + {MSec, Sec, USec} = now(), + -((MSec*1000000 + Sec)*1000000 + USec). diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 4ec848b23..1609b447d 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -431,6 +431,8 @@ process_term(Term, State) -> add_option(captcha_cmd, Cmd, State); {captcha_host, Host} -> add_option(captcha_host, Host, State); + {captcha_limit, Limit} -> + add_option(captcha_limit, Limit, State); {ejabberdctl_access_commands, ACs} -> add_option(ejabberdctl_access_commands, ACs, State); {loglevel, Loglevel} -> diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 9d275d496..bf60f72e5 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -1629,19 +1629,28 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) -> From, Err), StateData; captcha_required -> - ID = randoms:get_string(), SID = xml:get_attr_s("id", Attrs), RoomJID = StateData#state.jid, To = jlib:jid_replace_resource(RoomJID, Nick), + Limiter = {From#jid.luser, From#jid.lserver}, case ejabberd_captcha:create_captcha( - ID, SID, RoomJID, To, Lang, From) of - {ok, CaptchaEls} -> + SID, RoomJID, To, Lang, Limiter, From) of + {ok, ID, CaptchaEls} -> MsgPkt = {xmlelement, "message", [{"id", ID}], CaptchaEls}, Robots = ?DICT:store(From, {Nick, Packet}, StateData#state.robots), ejabberd_router:route(RoomJID, From, MsgPkt), StateData#state{robots = Robots}; - error -> + {error, limit} -> + ErrText = "Too many CAPTCHA requests", + Err = jlib:make_error_reply( + Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)), + ejabberd_router:route( % TODO: s/Nick/""/ + jlib:jid_replace_resource( + StateData#state.jid, Nick), + From, Err), + StateData; + _ -> ErrText = "Unable to generate a captcha", Err = jlib:make_error_reply( Packet, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)), diff --git a/src/mod_register.erl b/src/mod_register.erl index 4b90be8df..da1e21bdc 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -234,13 +234,18 @@ process_iq(From, To, {"var", "password"}], [{xmlelement, "required", [], []}]}, case ejabberd_captcha:create_captcha_x( - ID, To, Lang, [InstrEl, UField, PField]) of + ID, To, Lang, Source, [InstrEl, UField, PField]) of {ok, CaptchaEls} -> IQ#iq{type = result, sub_el = [{xmlelement, "query", [{"xmlns", "jabber:iq:register"}], [TopInstrEl | CaptchaEls]}]}; - error -> + {error, limit} -> + ErrText = "Too many CAPTCHA requests", + IQ#iq{type = error, + sub_el = [SubEl, ?ERRT_RESOURCE_CONSTRAINT( + Lang, ErrText)]}; + _Err -> ErrText = "Unable to generate a CAPTCHA", IQ#iq{type = error, sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR( diff --git a/src/web/mod_register_web.erl b/src/web/mod_register_web.erl index 2c6fda28f..98ee52fb9 100644 --- a/src/web/mod_register_web.erl +++ b/src/web/mod_register_web.erl @@ -86,8 +86,9 @@ process([], #request{method = 'GET', lang = Lang}) -> process(["register.css"], #request{method = 'GET'}) -> serve_css(); -process(["new"], #request{method = 'GET', lang = Lang, host = Host}) -> - form_new_get(Host, Lang); +process(["new"], #request{method = 'GET', lang = Lang, host = Host, ip = IP}) -> + {Addr, _Port} = IP, + form_new_get(Host, Lang, Addr); process(["delete"], #request{method = 'GET', lang = Lang, host = Host}) -> form_del_get(Host, Lang); @@ -185,8 +186,8 @@ index_page(Lang) -> %%% Formulary new account GET %%%---------------------------------------------------------------------- -form_new_get(Host, Lang) -> - CaptchaEls = build_captcha_li_list(Lang), +form_new_get(Host, Lang, IP) -> + CaptchaEls = build_captcha_li_list(Lang, IP), HeadEls = [ ?XCT("title", "Register a Jabber account"), ?XA("link", @@ -336,27 +337,31 @@ form_new_post(Username, Host, Password, {Id, Key}) -> %%% Formulary Captcha support for new GET/POST %%%---------------------------------------------------------------------- -build_captcha_li_list(Lang) -> +build_captcha_li_list(Lang, IP) -> case ejabberd_captcha:is_feature_available() of - true -> build_captcha_li_list2(Lang); + true -> build_captcha_li_list2(Lang, IP); false -> [] end. -build_captcha_li_list2(Lang) -> - Id = randoms:get_string(), +build_captcha_li_list2(Lang, IP) -> SID = "", From = #jid{user = "", server = "test", resource = ""}, To = #jid{user = "", server = "test", resource = ""}, Args = [], - ejabberd_captcha:create_captcha(Id, SID, From, To, Lang, Args), - {_, {CImg,CText,CId,CKey}} = ejabberd_captcha:build_captcha_html(Id, Lang), - [?XE("li", [CText, - ?C(" "), - CId, - CKey, - ?BR, - CImg] - )]. + case ejabberd_captcha:create_captcha(SID, From, To, Lang, IP, Args) of + {ok, Id, _} -> + {_, {CImg,CText,CId,CKey}} = + ejabberd_captcha:build_captcha_html(Id, Lang), + [?XE("li", [CText, + ?C(" "), + CId, + CKey, + ?BR, + CImg] + )]; + _ -> + [] + end. %%%---------------------------------------------------------------------- %%% Formulary change password GET From e7ab83b612c84c03e26c7ef1bd9cc56e53c5964a Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 18 Apr 2011 16:09:05 +1000 Subject: [PATCH 27/47] Remove forgotten -compile(export_all). --- src/ejabberd_captcha.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 428346aba..ff0bd0d25 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -27,7 +27,7 @@ -module(ejabberd_captcha). -behaviour(gen_server). --compile(export_all). + %% API -export([start_link/0]). From 72299ab078d343977a1ecdeb34cec0beaec54049 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 18 Apr 2011 16:16:10 +1000 Subject: [PATCH 28/47] Add captcha_limit option to the example config --- src/ejabberd.cfg.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example index 0912bf559..c776a8cb9 100644 --- a/src/ejabberd.cfg.example +++ b/src/ejabberd.cfg.example @@ -479,6 +479,10 @@ %% %%{captcha_host, "example.org:5280"}. +%% +%% Limit CAPTCHA calls per minute for JID/IP to avoid DoS. +%% +%%{captcha_limit, 5}. %%%. ======= %%%' MODULES From 897b46c31deb2a9df959564d2c1cb7d847344bc4 Mon Sep 17 00:00:00 2001 From: jabber Date: Sun, 17 Apr 2011 19:03:07 +0400 Subject: [PATCH 29/47] Do not decrease MUC admin's role/affiliation --- src/mod_muc/mod_muc_room.erl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index bf60f72e5..f5a1f4a4e 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -2519,6 +2519,11 @@ can_change_ra(_FAffiliation, _FRole, %% A room owner tries to add as persistent owner a %% participant that is already owner because he is MUC admin true; +can_change_ra(_FAffiliation, _FRole, + _TAffiliation, _TRole, + _RoleorAffiliation, _Value, owner) -> + %% Nobody can decrease MUC admin's role/affiliation + false; can_change_ra(_FAffiliation, _FRole, TAffiliation, _TRole, affiliation, Value, _ServiceAf) From 9b145385afa4fe300497c1925202bb2f9acc4e9d Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 26 Apr 2011 13:59:08 +0200 Subject: [PATCH 30/47] Throw error when captcha fails at server start, not later at runtime --- src/ejabberd_captcha.erl | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index ff0bd0d25..250dd333c 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -428,10 +428,10 @@ get_prog_name() -> case ejabberd_config:get_local_option(captcha_cmd) of FileName when is_list(FileName) -> FileName; - _ -> + Value when (Value == undefined) or (Value == "") -> ?DEBUG("The option captcha_cmd is not configured, but some " "module wants to use the CAPTCHA feature.", []), - throw({error, option_not_configured_captcha_cmd}) + false end. get_url(Str) -> @@ -552,23 +552,10 @@ return(Port, TRef, Result) -> catch port_close(Port), Result. -is_feature_enabled() -> - try get_prog_name() of - Prog when is_list(Prog) -> true - catch - _:_ -> false - end. - is_feature_available() -> - case is_feature_enabled() of - false -> false; - true -> - %% Do not generate image in order to avoid CAPTCHA DoS - %% case create_image() of - %% {ok, _, _, _} -> true; - %% _Error -> false - %% end - true + case get_prog_name() of + Prog when is_list(Prog) -> true; + false -> false end. check_captcha_setup() -> @@ -576,10 +563,11 @@ check_captcha_setup() -> {ok, _, _, _} -> true; _Error -> false end, - case is_feature_enabled() andalso not AbleToGenerateCaptcha of + case is_feature_available() andalso not AbleToGenerateCaptcha of true -> ?CRITICAL_MSG("Captcha is enabled in the option captcha_cmd, " - "but it can't generate images.", []); + "but it can't generate images.", []), + throw({error, captcha_cmd_enabled_but_fails}); false -> ok end. From 3952888f94457af484fe6f1cab1a457f5515d24f Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 26 Apr 2011 20:35:25 +0200 Subject: [PATCH 31/47] Escape user input in mod_privacy_odbc (EJAB-1442) --- src/mod_privacy_odbc.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_privacy_odbc.erl b/src/mod_privacy_odbc.erl index 64543faa8..2df9ee27a 100644 --- a/src/mod_privacy_odbc.erl +++ b/src/mod_privacy_odbc.erl @@ -751,9 +751,9 @@ item_to_raw(#listitem{type = Type, none -> {"n", ""}; jid -> - {"j", jlib:jid_to_string(Value)}; + {"j", ejabberd_odbc:escape(jlib:jid_to_string(Value))}; group -> - {"g", Value}; + {"g", ejabberd_odbc:escape(Value)}; subscription -> case Value of none -> From 4f4c8eb61eba2fcf35e4d6f9e7c13c2576ebe60c Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 26 Apr 2011 22:55:04 +0200 Subject: [PATCH 32/47] mod_register Access now also controls account unregistrations --- doc/guide.tex | 9 +++++---- src/mod_register.erl | 6 ++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/guide.tex b/doc/guide.tex index 5c157aa37..ce57c3c9f 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -3820,10 +3820,11 @@ enables end users to use a \XMPP{} client to: Options: \begin{description} -\titem{\{access, AccessName\}} \ind{options!access}This option can be configured to specify - rules to restrict registration. If a rule returns `deny' on the requested - user name, registration for that user name is denied. (there are no - restrictions by default). +\titem{\{access, AccessName\}} \ind{options!access} + Specify rules to restrict what usernames can be registered and unregistered. + If a rule returns `deny' on the requested username, + registration and unregistration of that user name is denied. + There are no restrictions by default. \titem{\{access\_from, AccessName\}} \ind{options!access\_from}By default, \ejabberd{} doesn't allow to register new accounts from s2s or existing c2s sessions. You can change it by defining access rule in this option. Use with care: allowing registration diff --git a/src/mod_register.erl b/src/mod_register.erl index da1e21bdc..048678373 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -106,8 +106,10 @@ process_iq(From, To, PTag = xml:get_subtag(SubEl, "password"), RTag = xml:get_subtag(SubEl, "remove"), Server = To#jid.lserver, + Access = gen_mod:get_module_opt(Server, ?MODULE, access, all), + AllowRemove = (allow == acl:match_rule(Server, Access, From)), if - (UTag /= false) and (RTag /= false) -> + (UTag /= false) and (RTag /= false) and AllowRemove -> User = xml:get_tag_cdata(UTag), case From of #jid{user = User, lserver = Server} -> @@ -148,7 +150,7 @@ process_iq(From, To, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end end; - (UTag == false) and (RTag /= false) -> + (UTag == false) and (RTag /= false) and AllowRemove -> case From of #jid{user = User, lserver = Server, From 4a2f62062ed2b729b464b37f2ee0e9e17328a296 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 15 Nov 2010 01:09:46 +0900 Subject: [PATCH 33/47] New migration procedure --- src/ejabberd_c2s.erl | 20 ++++----- src/ejabberd_cluster.erl | 69 ++++++++++++++++++++++-------- src/ejabberd_s2s.erl | 4 +- src/ejabberd_sm.erl | 81 ++++++++++++++++++++++++++++++------ src/mod_muc/mod_muc.erl | 81 ++++++++++++++++++++++++++++++------ src/mod_muc/mod_muc_room.erl | 12 ++++-- 6 files changed, 208 insertions(+), 59 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index a44f66a7d..4ff959217 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -194,7 +194,7 @@ stop(FsmRef) -> ?GEN_FSM:send_event(FsmRef, closed). migrate(FsmRef, Node, After) -> - ?GEN_FSM:send_all_state_event(FsmRef, {migrate, Node, After}). + erlang:send_after(After, FsmRef, {migrate, Node}). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm @@ -282,6 +282,7 @@ init([StateName, StateData, _FSMLimitOpts]) -> El -> get_priority_from_presence(El) end, + ejabberd_sm:drop_session(StateData#state.sid), ejabberd_sm:open_session( SID, StateData#state.user, @@ -289,6 +290,7 @@ init([StateName, StateData, _FSMLimitOpts]) -> StateData#state.resource, Priority, Info), + %%ejabberd_sm:drop_session(StateData#state.sid), NewStateData = StateData#state{sid = SID, socket_monitor = MRef}, StateData2 = change_reception(NewStateData, true), StateData3 = start_keepalive_timer(StateData2), @@ -1232,9 +1234,6 @@ session_established2(El, StateData) -> %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- -handle_event({migrate, Node, After}, StateName, StateData) when Node /= node() -> - fsm_migrate(StateName, StateData, Node, After * 2); - handle_event({add_rosteritem, IJID, ISubscription}, StateName, StateData) -> NewStateData = roster_change(IJID, ISubscription, StateData), fsm_next_state(StateName, NewStateData); @@ -1624,6 +1623,12 @@ handle_info({force_update_presence, LUser}, StateName, StateData end, {next_state, StateName, NewStateData}; +handle_info({migrate, Node}, StateName, StateData) -> + if Node /= node() -> + fsm_migrate(StateName, StateData, Node, 0); + true -> + fsm_next_state(StateName, StateData) + end; handle_info({broadcast, Type, From, Packet}, StateName, StateData) -> Recipients = ejabberd_hooks:run_fold( c2s_broadcast_recipients, StateData#state.server, @@ -2535,13 +2540,6 @@ maybe_migrate(StateName, StateData) -> StateData2 = change_reception(PackedStateData, true), StateData3 = start_keepalive_timer(StateData2), erlang:garbage_collect(), - case ejabberd_cluster:get_node_new({U, S}) of - Node -> - ok; - NewNode -> - After = ejabberd_cluster:rehash_timeout(), - migrate(self(), NewNode, After) - end, fsm_next_state(StateName, StateData3); Node -> fsm_migrate(StateName, PackedStateData, Node, 0) diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl index c189eb450..bdae7039f 100644 --- a/src/ejabberd_cluster.erl +++ b/src/ejabberd_cluster.erl @@ -22,7 +22,11 @@ -define(HASHTBL, nodes_hash). -define(HASHTBL_NEW, nodes_hash_new). -define(POINTS, 64). --define(REHASH_TIMEOUT, 30000). +-define(REHASH_TIMEOUT, timer:seconds(30)). +-define(MIGRATE_TIMEOUT, timer:minutes(2)). +%%-define(REHASH_TIMEOUT, timer:seconds(10)). +%%-define(MIGRATE_TIMEOUT, timer:seconds(5)). +-define(LOCK, {migrate, node()}). -record(state, {}). @@ -80,13 +84,16 @@ shutdown() -> %% gen_server callbacks %%==================================================================== init([]) -> + {A, B, C} = now(), + random:seed(A, B, C), net_kernel:monitor_nodes(true, [{node_type, visible}]), ets:new(?HASHTBL, [named_table, public, ordered_set]), ets:new(?HASHTBL_NEW, [named_table, public, ordered_set]), register_node(), - AllNodes = mnesia:system_info(running_db_nodes), + pg2:create(?MODULE), + AllNodes = cluster_group(), OtherNodes = case AllNodes of - [_] -> + [_MyNode] -> AllNodes; _ -> AllNodes -- [node()] @@ -96,35 +103,55 @@ init([]) -> {ok, #state{}}. handle_call(announce, _From, State) -> - case mnesia:system_info(running_db_nodes) of + case global:set_lock(?LOCK, cluster_group(), 0) of + false -> + ?INFO_MSG("Another node is recently attached to " + "the cluster and is being rebalanced. " + "Waiting for the rebalancing to be completed " + "before starting this node. " + "This may take serveral minutes. " + "Please, be patient.", []), + global:set_lock(?LOCK, cluster_group(), infinity); + true -> + ok + end, + case cluster_group() of [_MyNode] -> - ok; + join_cluster_group(), + global:del_lock(?LOCK); Nodes -> OtherNodes = Nodes -- [node()], - lists:foreach( - fun(Node) -> - {?MODULE, Node} ! {node_ready, node()} - end, OtherNodes), ?INFO_MSG("waiting for migration from nodes: ~w", [OtherNodes]), - timer:sleep(?REHASH_TIMEOUT), - append_node(?HASHTBL, node()) + {_Res, BadNodes} = gen_server:multi_call( + OtherNodes, ?MODULE, + {node_ready, node()}, ?REHASH_TIMEOUT), + append_node(?HASHTBL, node()), + join_cluster_group(), + gen_server:abcast(OtherNodes -- BadNodes, + ?MODULE, {node_ready, node()}), + erlang:send_after(?MIGRATE_TIMEOUT, self(), del_lock) end, {reply, ok, State}; +handle_call({node_ready, Node}, _From, State) -> + ?INFO_MSG("node ~p is ready, preparing migration", [Node]), + append_node(?HASHTBL_NEW, Node), + ejabberd_hooks:run(node_up, [Node]), + {reply, ok, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. +handle_cast({node_ready, Node}, State) -> + ?INFO_MSG("adding node ~p to hash and starting migration", [Node]), + append_node(?HASHTBL, Node), + ejabberd_hooks:run(node_hash_update, [?MIGRATE_TIMEOUT]), + {noreply, State}; handle_cast(_Msg, State) -> {noreply, State}. -handle_info({node_ready, Node}, State) -> - ?INFO_MSG("node ~p is ready, starting migration", [Node]), - append_node(?HASHTBL_NEW, Node), - ejabberd_hooks:run(node_hash_update, [?REHASH_TIMEOUT]), - timer:sleep(?REHASH_TIMEOUT), - ?INFO_MSG("adding node ~p to hash", [Node]), - append_node(?HASHTBL, Node), +handle_info(del_lock, State) -> + global:del_lock(?LOCK), {noreply, State}; handle_info({node_down, Node}, State) -> delete_node(?HASHTBL, Node), @@ -187,3 +214,9 @@ get_node_by_hash(Tab, Hash) -> register_node() -> global:register_name(list_to_atom(node_id()), self()). + +cluster_group() -> + [node() | [node(P) || P <- pg2:get_members(?MODULE)]]. + +join_cluster_group() -> + pg2:join(?MODULE, whereis(?MODULE)). diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 13c2d6d07..99403f75c 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -203,9 +203,9 @@ migrate(After) -> ['$$']}]), lists:foreach( fun([FromTo, Pid]) -> - case ejabberd_cluster:get_node_new(FromTo) of + case ejabberd_cluster:get_node(FromTo) of Node when Node /= node() -> - ejabberd_s2s_out:stop_connection(Pid, After * 2); + ejabberd_s2s_out:stop_connection(Pid, After); _ -> ok end diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index cca7db502..dd347edc9 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -37,6 +37,7 @@ open_session/6, close_session/4, close_migrated_session/4, + drop_session/1, check_in_subscription/6, bounce_offline_message/3, disconnect_removed_user/2, @@ -60,6 +61,7 @@ get_session_pid/3, get_user_info/3, get_user_ip/3, + node_up/1, migrate/1 ]). @@ -108,27 +110,37 @@ open_session(SID, User, Server, Resource, Priority, Info) -> [SID, JID, Info]). close_session(SID, User, Server, Resource) -> - Info = do_close_session(SID, User, Server, Resource), + Info = do_close_session(SID), + US = {jlib:nodeprep(User), jlib:nameprep(Server)}, + case ejabberd_cluster:get_node_new(US) of + Node when Node /= node() -> + rpc:cast(Node, ?MODULE, drop_session, [SID]); + _ -> + ok + end, JID = jlib:make_jid(User, Server, Resource), ejabberd_hooks:run(sm_remove_connection_hook, JID#jid.lserver, [SID, JID, Info]). close_migrated_session(SID, User, Server, Resource) -> - Info = do_close_session(SID, User, Server, Resource), + Info = do_close_session(SID), JID = jlib:make_jid(User, Server, Resource), ejabberd_hooks:run(sm_remove_migrated_connection_hook, JID#jid.lserver, [SID, JID, Info]). -do_close_session(SID, User, Server, Resource) -> +do_close_session(SID) -> Info = case mnesia:dirty_read({session, SID}) of - [] -> []; - [#session{info=I}] -> I - end, + [] -> []; + [#session{info=I}] -> I + end, + drop_session(SID), + Info. + +drop_session(SID) -> F = fun() -> mnesia:delete({session, SID}) end, - mnesia:sync_dirty(F), - Info. + mnesia:sync_dirty(F). check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) -> case ejabberd_auth:is_user_exists(User, Server) of @@ -312,14 +324,33 @@ migrate(After) -> ['$$']}]), lists:foreach( fun([US, Pid]) -> - case ejabberd_cluster:get_node_new(US) of + case ejabberd_cluster:get_node(US) of Node when Node /= node() -> - ejabberd_c2s:migrate(Pid, Node, After); + ejabberd_c2s:migrate(Pid, Node, random:uniform(After)); _ -> ok end end, Ss). +node_up(_Node) -> + copy_sessions(mnesia:dirty_first(session)). + +copy_sessions('$end_of_table') -> + ok; +copy_sessions(Key) -> + case mnesia:dirty_read(session, Key) of + [#session{us = US} = Session] -> + case ejabberd_cluster:get_node_new(US) of + Node when node() /= Node -> + rpc:cast(Node, mnesia, dirty_write, [Session]); + _ -> + ok + end; + _ -> + ok + end, + copy_sessions(mnesia:dirty_next(session, Key)). + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -341,6 +372,7 @@ init([]) -> mnesia:add_table_index(session, us), mnesia:add_table_copy(session, node(), ram_copies), ets:new(sm_iqtable, [named_table]), + ejabberd_hooks:add(node_up, ?MODULE, node_up, 100), ejabberd_hooks:add(node_hash_update, ?MODULE, migrate, 100), lists:foreach( fun(Host) -> @@ -418,6 +450,7 @@ handle_info(_Info, State) -> %% The return value is ignored. %%-------------------------------------------------------------------- terminate(_Reason, _State) -> + ejabberd_hooks:delete(node_up, ?MODULE, node_up, 100), ejabberd_hooks:delete(node_hash_update, ?MODULE, migrate, 100), ejabberd_commands:unregister_commands(commands()), ok. @@ -433,7 +466,7 @@ code_change(_OldVsn, State, _Extra) -> %%% Internal functions %%-------------------------------------------------------------------- -set_session(SID, User, Server, Resource, Priority, Info) -> +set_session({_, Pid} = SID, User, Server, Resource, Priority, Info) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), LResource = jlib:resourceprep(Resource), @@ -446,7 +479,31 @@ set_session(SID, User, Server, Resource, Priority, Info) -> priority = Priority, info = Info}) end, - mnesia:sync_dirty(F). + mnesia:sync_dirty(F), + case ejabberd_cluster:get_node_new(US) of + Node when node() /= Node -> + %% New node has just been added. But we may miss session records + %% copy procedure, so we copy the session record manually just + %% to make sure + rpc:cast(Node, mnesia, dirty_write, + [#session{sid = SID, + usr = USR, + us = US, + priority = Priority, + info = Info}]), + case ejabberd_cluster:get_node(US) of + Node when node() /= Node -> + %% Migration to new node has completed, and seems like + %% we missed it, so we migrate the session pid manually. + %% It is not a problem if we have already got migration + %% notification: dups are just ignored by the c2s pid. + ejabberd_c2s:migrate(Pid, Node, 0); + _ -> + ok + end; + _ -> + ok + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/mod_muc/mod_muc.erl b/src/mod_muc/mod_muc.erl index ff6482f73..ff329e5b6 100644 --- a/src/mod_muc/mod_muc.erl +++ b/src/mod_muc/mod_muc.erl @@ -42,6 +42,7 @@ process_iq_disco_items/4, broadcast_service_message/2, register_room/3, + node_up/1, migrate/1, get_vh_rooms/1, can_use_nick/3]). @@ -175,14 +176,33 @@ migrate(After) -> ['$$']}]), lists:foreach( fun([NameHost, Pid]) -> - case ejabberd_cluster:get_node_new(NameHost) of + case ejabberd_cluster:get_node(NameHost) of Node when Node /= node() -> - mod_muc_room:migrate(Pid, Node, After); + mod_muc_room:migrate(Pid, Node, random:uniform(After)); _ -> ok end end, Rs). +node_up(Node) -> + copy_rooms(mnesia:dirty_first(muc_online_room)). + +copy_rooms('$end_of_table') -> + ok; +copy_rooms(Key) -> + case mnesia:dirty_read(muc_online_room, Key) of + [#muc_online_room{name_host = NameHost} = Room] -> + case ejabberd_cluster:get_node_new(NameHost) of + Node when node() /= Node -> + rpc:cast(Node, mnesia, dirty_write, [Room]); + _ -> + ok + end; + _ -> + ok + end, + copy_rooms(mnesia:dirty_next(muc_online_room, Key)). + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -219,6 +239,7 @@ init([Host, Opts]) -> DefRoomOpts = gen_mod:get_opt(default_room_options, Opts, []), RoomShaper = gen_mod:get_opt(room_shaper, Opts, none), ejabberd_router:register_route(MyHost), + ejabberd_hooks:add(node_up, ?MODULE, node_up, 100), ejabberd_hooks:add(node_hash_update, ?MODULE, migrate, 100), load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent}, @@ -306,7 +327,15 @@ handle_info({room_destroyed, RoomHost, Pid}, State) -> mnesia:delete_object(#muc_online_room{name_host = RoomHost, pid = Pid}) end, - mnesia:sync_dirty(F), + mnesia:async_dirty(F), + case ejabberd_cluster:get_node_new(RoomHost) of + Node when Node /= node() -> + rpc:cast(Node, mnesia, dirty_delete_object, + [#muc_online_room{name_host = RoomHost, + pid = Pid}]); + _ -> + ok + end, {noreply, State}; handle_info(_Info, State) -> {noreply, State}. @@ -319,6 +348,7 @@ handle_info(_Info, State) -> %% The return value is ignored. %%-------------------------------------------------------------------- terminate(_Reason, State) -> + ejabberd_hooks:delete(node_up, ?MODULE, node_up, 100), ejabberd_hooks:delete(node_hash_update, ?MODULE, migrate, 100), ejabberd_router:unregister_route(State#state.host), ok. @@ -507,14 +537,20 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, AccessCreate, From, Room) of true -> - {ok, Pid} = start_new_room( - Host, ServerHost, Access, - Room, HistorySize, - RoomShaper, From, - Nick, DefRoomOpts), - register_room(Host, Room, Pid), - mod_muc_room:route(Pid, From, Nick, Packet), - ok; + case start_new_room( + Host, ServerHost, Access, + Room, HistorySize, + RoomShaper, From, + Nick, DefRoomOpts) of + {ok, Pid} -> + mod_muc_room:route(Pid, From, Nick, Packet), + register_room(Host, Room, Pid), + ok; + _Err -> + Err = jlib:make_error_reply( + Packet, ?ERR_INTERNAL_SERVER_ERROR), + ejabberd_router:route(To, From, Err) + end; false -> Lang = xml:get_attr_s("xml:lang", Attrs), ErrText = "Room creation is denied by service policy", @@ -603,7 +639,28 @@ register_room(Host, Room, Pid) -> mnesia:write(#muc_online_room{name_host = {Room, Host}, pid = Pid}) end, - mnesia:sync_dirty(F). + mnesia:async_dirty(F), + case ejabberd_cluster:get_node_new({Room, Host}) of + Node when Node /= node() -> + %% New node has just been added. But we may miss MUC records + %% copy procedure, so we copy the MUC record manually just + %% to make sure + rpc:cast(Node, mnesia, dirty_write, + [#muc_online_room{name_host = {Room, Host}, + pid = Pid}]), + case ejabberd_cluster:get_node({Room, Host}) of + Node when node() /= Node -> + %% Migration to new node has completed, and seems like + %% we missed it, so we migrate the MUC room pid manually. + %% It is not a problem if we have already got migration + %% notification: dups are just ignored by the MUC room pid. + mod_muc_room:migrate(Pid, Node, 0); + _ -> + ok + end; + _ -> + ok + end. iq_disco_info(Lang) -> [{xmlelement, "identity", diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 913d408d6..2891cf261 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -110,7 +110,7 @@ start_link(StateName, StateData) -> ?GEN_FSM:start_link(?MODULE, [StateName, StateData], ?FSMOPTS). migrate(FsmRef, Node, After) -> - ?GEN_FSM:send_all_state_event(FsmRef, {migrate, Node, After}). + erlang:send_after(After, FsmRef, {migrate, Node}). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm @@ -597,9 +597,6 @@ handle_event(destroy, StateName, StateData) -> handle_event({set_affiliations, Affiliations}, StateName, StateData) -> {next_state, StateName, StateData#state{affiliations = Affiliations}}; -handle_event({migrate, Node, After}, StateName, StateData) when Node /= node() -> - {migrate, StateData, - {Node, ?MODULE, start, [StateName, StateData]}, After * 2}; handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. @@ -716,6 +713,13 @@ handle_info({captcha_failed, From}, normal_state, StateData) -> StateData end, {next_state, normal_state, NewState}; +handle_info({migrate, Node}, StateName, StateData) -> + if Node /= node() -> + {migrate, StateData, + {Node, ?MODULE, start, [StateName, StateData]}, 0}; + true -> + {next_state, StateName, StateData} + end; handle_info(_Info, StateName, StateData) -> {next_state, StateName, StateData}. From 2f16a160c03fc3f2820ba08453ab9cb4b594f804 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 15 Nov 2010 02:42:25 +0900 Subject: [PATCH 34/47] Shadow unused variable --- src/mod_muc/mod_muc.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_muc/mod_muc.erl b/src/mod_muc/mod_muc.erl index ff329e5b6..078cb36c7 100644 --- a/src/mod_muc/mod_muc.erl +++ b/src/mod_muc/mod_muc.erl @@ -184,7 +184,7 @@ migrate(After) -> end end, Rs). -node_up(Node) -> +node_up(_Node) -> copy_rooms(mnesia:dirty_first(muc_online_room)). copy_rooms('$end_of_table') -> From 658ab235ba1f22a9e69752f6c13d71a7e23d33aa Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 16 Nov 2010 15:29:07 +0900 Subject: [PATCH 35/47] Get rid of pg2 in cluster nodes --- src/ejabberd_app.erl | 3 ++- src/ejabberd_cluster.erl | 38 ++++++++++++++++++++------------------ src/ejabberd_sup.erl | 8 -------- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 1d9417d81..7d349b2cc 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -68,7 +68,8 @@ start(normal, _Args) -> %ejabberd_debug:fprof_start(), maybe_add_nameservers(), start_modules(), - ejabberd_cluster:announce(), + {ok, Pid} = ejabberd_cluster:start(), + ejabberd_cluster:announce(Pid), ejabberd_node_groups:start(), ejabberd_listener:start_listeners(), ?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]), diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl index bdae7039f..e537e1faa 100644 --- a/src/ejabberd_cluster.erl +++ b/src/ejabberd_cluster.erl @@ -10,8 +10,8 @@ -behaviour(gen_server). %% API --export([start_link/0, get_node/1, get_node_new/1, announce/0, shutdown/0, - node_id/0, get_node_by_id/1, get_nodes/0, rehash_timeout/0]). +-export([start_link/0, get_node/1, get_node_new/1, announce/1, shutdown/0, + node_id/0, get_node_by_id/1, get_nodes/0, rehash_timeout/0, start/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -33,8 +33,17 @@ %%==================================================================== %% API %%==================================================================== +start() -> + ChildSpec = {?MODULE, + {?MODULE, start_link, []}, + permanent, + brutal_kill, + worker, + [?MODULE]}, + supervisor:start_child(ejabberd_sup, ChildSpec). + start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + gen_server:start_link(?MODULE, [], []). get_node(Key) -> Hash = erlang:phash2(Key), @@ -48,8 +57,8 @@ get_nodes() -> %% TODO mnesia:system_info(running_db_nodes). -announce() -> - gen_server:call(?MODULE, announce, infinity). +announce(Pid) -> + gen_server:call(Pid, announce, infinity). node_id() -> integer_to_list(erlang:phash2(node())). @@ -90,8 +99,7 @@ init([]) -> ets:new(?HASHTBL, [named_table, public, ordered_set]), ets:new(?HASHTBL_NEW, [named_table, public, ordered_set]), register_node(), - pg2:create(?MODULE), - AllNodes = cluster_group(), + AllNodes = get_nodes(), OtherNodes = case AllNodes of [_MyNode] -> AllNodes; @@ -103,7 +111,7 @@ init([]) -> {ok, #state{}}. handle_call(announce, _From, State) -> - case global:set_lock(?LOCK, cluster_group(), 0) of + case global:set_lock(?LOCK, get_nodes(), 0) of false -> ?INFO_MSG("Another node is recently attached to " "the cluster and is being rebalanced. " @@ -111,13 +119,13 @@ handle_call(announce, _From, State) -> "before starting this node. " "This may take serveral minutes. " "Please, be patient.", []), - global:set_lock(?LOCK, cluster_group(), infinity); + global:set_lock(?LOCK, get_nodes(), infinity); true -> ok end, - case cluster_group() of + case get_nodes() of [_MyNode] -> - join_cluster_group(), + register(?MODULE, self()), global:del_lock(?LOCK); Nodes -> OtherNodes = Nodes -- [node()], @@ -127,7 +135,7 @@ handle_call(announce, _From, State) -> OtherNodes, ?MODULE, {node_ready, node()}, ?REHASH_TIMEOUT), append_node(?HASHTBL, node()), - join_cluster_group(), + register(?MODULE, self()), gen_server:abcast(OtherNodes -- BadNodes, ?MODULE, {node_ready, node()}), erlang:send_after(?MIGRATE_TIMEOUT, self(), del_lock) @@ -214,9 +222,3 @@ get_node_by_hash(Tab, Hash) -> register_node() -> global:register_name(list_to_atom(node_id()), self()). - -cluster_group() -> - [node() | [node(P) || P <- pg2:get_members(?MODULE)]]. - -join_cluster_group() -> - pg2:join(?MODULE, whereis(?MODULE)). diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index ca531cf1d..f7c303333 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -178,13 +178,6 @@ init([]) -> infinity, supervisor, [ejabberd_tmp_sup]}, - Cluster = - {ejabberd_cluster, - {ejabberd_cluster, start_link, []}, - permanent, - brutal_kill, - worker, - [ejabberd_cluster]}, CacheTabSupervisor = {cache_tab_sup, {cache_tab_sup, start_link, []}, @@ -194,7 +187,6 @@ init([]) -> [cache_tab_sup]}, {ok, {{one_for_one, 10, 1}, [Hooks, - Cluster, SystemMonitor, Router, SM, From 24e033ac7916b3e56ab10f0a0c9c9896c32ae524 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 16 Feb 2011 19:14:08 +0900 Subject: [PATCH 36/47] Initialize cluster before modules start --- src/ejabberd_app.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 7d349b2cc..2caef6e1f 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -67,8 +67,8 @@ start(normal, _Args) -> %ejabberd_debug:eprof_start(), %ejabberd_debug:fprof_start(), maybe_add_nameservers(), - start_modules(), {ok, Pid} = ejabberd_cluster:start(), + start_modules(), ejabberd_cluster:announce(Pid), ejabberd_node_groups:start(), ejabberd_listener:start_listeners(), From 70e84021f222275f12e91302aab95aeb0a59ea4f Mon Sep 17 00:00:00 2001 From: jabber Date: Sun, 17 Apr 2011 06:05:48 +0400 Subject: [PATCH 37/47] Remove global lock if there are no nodes available --- src/ejabberd_cluster.erl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl index e537e1faa..bc2f85da6 100644 --- a/src/ejabberd_cluster.erl +++ b/src/ejabberd_cluster.erl @@ -136,9 +136,13 @@ handle_call(announce, _From, State) -> {node_ready, node()}, ?REHASH_TIMEOUT), append_node(?HASHTBL, node()), register(?MODULE, self()), - gen_server:abcast(OtherNodes -- BadNodes, - ?MODULE, {node_ready, node()}), - erlang:send_after(?MIGRATE_TIMEOUT, self(), del_lock) + case OtherNodes -- BadNodes of + [] -> + global:del_lock(?LOCK); + WorkingNodes -> + gen_server:abcast(WorkingNodes, ?MODULE, {node_ready, node()}), + erlang:send_after(?MIGRATE_TIMEOUT, self(), del_lock) + end end, {reply, ok, State}; handle_call({node_ready, Node}, _From, State) -> From 49365da48141c73c4a2351f90879912c08cd4754 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 17 Apr 2011 19:48:57 +1000 Subject: [PATCH 38/47] Stringprep JID before get_node calculation --- src/ejabberd_c2s.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 4ff959217..e87128949 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2521,13 +2521,12 @@ peerip(SockMod, Socket) -> maybe_migrate(StateName, StateData) -> PackedStateData = pack(StateData), - case ejabberd_cluster:get_node({StateData#state.user, - StateData#state.server}) of + #state{user = U, server = S, resource = R, sid = SID} = StateData, + case ejabberd_cluster:get_node({jlib:nodeprep(U), jlib:nameprep(S)}) of Node when Node == node() -> Conn = get_conn_type(StateData), Info = [{ip, StateData#state.ip}, {conn, Conn}, {auth_module, StateData#state.auth_module}], - #state{user = U, server = S, resource = R, sid = SID} = StateData, Presence = StateData#state.pres_last, Priority = case Presence of From b807b21a596b7bb95e5578773175404453212f57 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 28 Apr 2011 13:24:18 +0200 Subject: [PATCH 39/47] Show configuration for HTTPS http_bind --- doc/guide.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/guide.tex b/doc/guide.tex index ce57c3c9f..9352511a6 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -1028,7 +1028,7 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi \item Port 5269 listens for s2s connections with STARTTLS. The socket is set for IPv6 instead of IPv4. \item Port 3478 listens for STUN requests over UDP. \item Port 5280 listens for HTTP requests, and serves the HTTP Poll service. -\item Port 5281 listens for HTTP requests, and serves the Web Admin using HTTPS as explained in +\item Port 5281 listens for HTTP requests, using HTTPS to serve HTTP-Bind (BOSH) and the Web Admin as explained in section~\ref{webadmin}. The socket only listens connections to the IP address 127.0.0.1. \end{itemize} \begin{verbatim} @@ -1057,6 +1057,7 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi ]}, {{5281, "127.0.0.1"}, ejabberd_http, [ web_admin, + http_bind, tls, {certfile, "/etc/ejabberd/server.pem"}, ]} ] From a97a60a888eb186b440830136953cb1dde2184b3 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 7 Apr 2011 15:59:20 +1000 Subject: [PATCH 40/47] Fix previous merge --- src/ejabberd_local.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index bf1a12583..4d5f2ecb4 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -150,10 +150,10 @@ register_iq_response_handler(_Host, ID, Module, Function, Timeout0) -> N end, TRef = erlang:start_timer(Timeout, ejabberd_local, ID), - mnesia:dirty_write(#iq_response{id = ID, - module = Module, - function = Function, - timer = TRef}). + ets:insert(iq_response, #iq_response{id = ID, + module = Module, + function = Function, + timer = TRef}). register_iq_handler(Host, XMLNS, Module, Fun) -> ejabberd_local ! {register_iq_handler, Host, XMLNS, Module, Fun}. From 714dce84dbdae8b94d4abfc54b3973620b0e6f4c Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 29 Apr 2011 20:12:58 +0200 Subject: [PATCH 41/47] No need to inform that XEP-0237 is optional; clarified in XEP version 1.2 --- src/mod_roster.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 6ffbca2fe..f611136da 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -161,7 +161,7 @@ get_versioning_feature(Acc, Host) -> Feature = {xmlelement, "ver", [{"xmlns", ?NS_ROSTER_VER}], - [{xmlelement, "optional", [], []}]}, + []}, [Feature | Acc]; false -> [] end. From 5a0cfe7e2bab0d42771cf99ddae63b429c78a553 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 29 Apr 2011 20:30:17 +0200 Subject: [PATCH 42/47] Reorganize the push_item function, and handle version not_found (EJAB-1420) --- src/mod_roster.erl | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/mod_roster.erl b/src/mod_roster.erl index f611136da..63162b4d0 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -411,10 +411,17 @@ push_item(User, Server, From, Item) -> % TODO: don't push to those who didn't load roster push_item(User, Server, Resource, From, Item) -> + push_item(User, Server, Resource, From, Item, not_found). + +push_item(User, Server, Resource, From, Item, RosterVersion) -> + ExtraAttrs = case RosterVersion of + not_found -> []; + _ -> [{"ver", RosterVersion}] + end, ResIQ = #iq{type = set, xmlns = ?NS_ROSTER, id = "push" ++ randoms:get_string(), sub_el = [{xmlelement, "query", - [{"xmlns", ?NS_ROSTER}], + [{"xmlns", ?NS_ROSTER}|ExtraAttrs], [item_to_xml(Item)]}]}, ejabberd_router:route( From, @@ -425,21 +432,9 @@ push_item(User, Server, Resource, From, Item) -> %% TODO: don't push to those who didn't load roster push_item_version(Server, User, From, Item, RosterVersion) -> lists:foreach(fun(Resource) -> - push_item_version(User, Server, Resource, From, Item, RosterVersion) + push_item(User, Server, Resource, From, Item, RosterVersion) end, ejabberd_sm:get_user_resources(User, Server)). -push_item_version(User, Server, Resource, From, Item, RosterVersion) -> - IQPush = #iq{type = 'set', xmlns = ?NS_ROSTER, - id = "push" ++ randoms:get_string(), - sub_el = [{xmlelement, "query", - [{"xmlns", ?NS_ROSTER}, - {"ver", RosterVersion}], - [item_to_xml(Item)]}]}, - ejabberd_router:route( - From, - jlib:make_jid(User, Server, Resource), - jlib:iq_to_xml(IQPush)). - get_subscription_lists(_, User, Server) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), From 38693a670bb8e265ca25fe1d4d5f9bb4103fcc22 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 7 Apr 2011 22:52:50 +1000 Subject: [PATCH 43/47] Process ejabberd_sm messages using several dispatchers (EJABS-1653) --- src/ejabberd_sm.erl | 72 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index dd347edc9..a96ae8a3a 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -384,7 +384,7 @@ init([]) -> ejabberd_sm, disconnect_removed_user, 100) end, ?MYHOSTS), ejabberd_commands:register_commands(commands()), - + start_dispatchers(), {ok, #state{}}. %%-------------------------------------------------------------------- @@ -415,13 +415,19 @@ handle_cast(_Msg, State) -> %% {stop, Reason, State} %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- -handle_info({route, From, To, Packet}, State) -> - case catch do_route(From, To, Packet) of - {'EXIT', Reason} -> - ?ERROR_MSG("~p~nwhen processing: ~p", - [Reason, {From, To, Packet}]); - _ -> - ok +handle_info({route, From, To, Packet} = Msg, State) -> + case get_proc_num() of + N when N > 1 -> + #jid{luser = U, lserver = S} = To, + get_proc_by_hash({U, S}) ! Msg; + _ -> + case catch do_route(From, To, Packet) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p~nwhen processing: ~p", + [Reason, {From, To, Packet}]); + _ -> + ok + end end, {noreply, State}; handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) -> @@ -453,6 +459,7 @@ terminate(_Reason, _State) -> ejabberd_hooks:delete(node_up, ?MODULE, node_up, 100), ejabberd_hooks:delete(node_hash_update, ?MODULE, migrate, 100), ejabberd_commands:unregister_commands(commands()), + stop_dispatchers(), ok. %%-------------------------------------------------------------------- @@ -875,6 +882,55 @@ user_resources(User, Server) -> Resources = get_user_resources(User, Server), lists:sort(Resources). +get_proc_num() -> + erlang:system_info(logical_processors). + +get_proc_by_hash(Term) -> + N = erlang:phash2(Term, get_proc_num()) + 1, + get_proc(N). + +get_proc(N) -> + list_to_atom(atom_to_list(?MODULE) ++ "_" ++ integer_to_list(N)). + +start_dispatchers() -> + case get_proc_num() of + N when N > 1 -> + lists:foreach( + fun(I) -> + Pid = spawn(fun dispatch/0), + erlang:register(get_proc(I), Pid) + end, lists:seq(1, N)); + _ -> + ok + end. + +stop_dispatchers() -> + case get_proc_num() of + N when N > 1 -> + lists:foreach( + fun(I) -> + get_proc(I) ! stop + end, lists:seq(1, N)); + _ -> + ok + end. + +dispatch() -> + receive + {route, From, To, Packet} -> + case catch do_route(From, To, Packet) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p~nwhen processing: ~p", + [Reason, {From, To, Packet}]); + _ -> + ok + end, + dispatch(); + stop -> + stopped; + _ -> + dispatch() + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Update Mnesia tables From 84c1cf80337e8a24f09d920af9615737763d4b97 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 3 May 2011 20:26:07 +1000 Subject: [PATCH 44/47] Do not accept XML with undefined prefixes (EJAB-680) --- src/expat_erl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/src/expat_erl.c b/src/expat_erl.c index 5a1ab63e0..08f298e07 100644 --- a/src/expat_erl.c +++ b/src/expat_erl.c @@ -35,6 +35,7 @@ #define PARSE_FINAL_COMMAND 1 ei_x_buff event_buf; +ei_x_buff xmlns_buf; typedef struct { ErlDrvPort port; @@ -43,6 +44,32 @@ typedef struct { static XML_Memory_Handling_Suite ms = {driver_alloc, driver_realloc, driver_free}; +void encode_name(const XML_Char *name) +{ + char *name_start; + char *prefix_start; + char *buf; + int name_len, prefix_len, buf_len; + + if ((name_start = strchr(name, '\n'))) { + if ((prefix_start = strchr(name_start+1, '\n'))) { + name_len = prefix_start - name_start; + prefix_len = strlen(prefix_start+1); + buf_len = prefix_len + name_len; + buf = driver_alloc(buf_len); + memcpy(buf, prefix_start+1, prefix_len); + memcpy(buf+prefix_len, name_start, name_len); + buf[prefix_len] = ':'; + ei_x_encode_string_len(&event_buf, buf, buf_len); + driver_free(buf); + } else { + ei_x_encode_string(&event_buf, name_start+1); + }; + } else { + ei_x_encode_string(&event_buf, name); + } +} + void *erlXML_StartElementHandler(expat_data *d, const XML_Char *name, const XML_Char **atts) @@ -53,7 +80,10 @@ void *erlXML_StartElementHandler(expat_data *d, ei_x_encode_tuple_header(&event_buf, 2); ei_x_encode_long(&event_buf, XML_START); ei_x_encode_tuple_header(&event_buf, 2); - ei_x_encode_string(&event_buf, name); + encode_name(name); + ei_x_append(&event_buf, &xmlns_buf); + ei_x_free(&xmlns_buf); + ei_x_new(&xmlns_buf); for (i = 0; atts[i]; i += 2) {} @@ -64,7 +94,7 @@ void *erlXML_StartElementHandler(expat_data *d, for (i = 0; atts[i]; i += 2) { ei_x_encode_tuple_header(&event_buf, 2); - ei_x_encode_string(&event_buf, atts[i]); + encode_name(atts[i]); ei_x_encode_string(&event_buf, atts[i+1]); } } @@ -80,7 +110,7 @@ void *erlXML_EndElementHandler(expat_data *d, ei_x_encode_list_header(&event_buf, 1); ei_x_encode_tuple_header(&event_buf, 2); ei_x_encode_long(&event_buf, XML_END); - ei_x_encode_string(&event_buf, name); + encode_name(name); return NULL; } @@ -95,12 +125,35 @@ void *erlXML_CharacterDataHandler(expat_data *d, return NULL; } +void *erlXML_StartNamespaceDeclHandler(expat_data *d, + const XML_Char *prefix, + const XML_Char *uri) +{ + int prefix_len; + char *buf; + + ei_x_encode_list_header(&xmlns_buf, 1); + ei_x_encode_tuple_header(&xmlns_buf, 2); + if (prefix) { + prefix_len = strlen(prefix); + buf = driver_alloc(7 + prefix_len); + strcpy(buf, "xmlns:"); + strcpy(buf+6, prefix); + ei_x_encode_string(&xmlns_buf, buf); + driver_free(buf); + } else { + ei_x_encode_string(&xmlns_buf, "xmlns"); + }; + ei_x_encode_string(&xmlns_buf, uri); + + return NULL; +} static ErlDrvData expat_erl_start(ErlDrvPort port, char *buff) { expat_data* d = (expat_data*)driver_alloc(sizeof(expat_data)); d->port = port; - d->parser = XML_ParserCreate_MM("UTF-8", &ms, NULL); + d->parser = XML_ParserCreate_MM("UTF-8", &ms, "\n"); XML_SetUserData(d->parser, d); set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); @@ -112,6 +165,9 @@ static ErlDrvData expat_erl_start(ErlDrvPort port, char *buff) XML_SetCharacterDataHandler( d->parser, (XML_CharacterDataHandler)erlXML_CharacterDataHandler); + XML_SetStartNamespaceDeclHandler( + d->parser, (XML_StartNamespaceDeclHandler) erlXML_StartNamespaceDeclHandler); + XML_SetReturnNSTriplet(d->parser, 1); return (ErlDrvData)d; } @@ -138,6 +194,7 @@ static int expat_erl_control(ErlDrvData drv_data, case PARSE_COMMAND: case PARSE_FINAL_COMMAND: ei_x_new_with_version(&event_buf); + ei_x_new(&xmlns_buf); res = XML_Parse(d->parser, buf, len, command == PARSE_FINAL_COMMAND); if(!res) @@ -161,6 +218,7 @@ static int expat_erl_control(ErlDrvData drv_data, memcpy(b->orig_bytes, event_buf.buff, size); ei_x_free(&event_buf); + ei_x_free(&xmlns_buf); *rbuf = (char *)b; return size; From 613214da18778b277185530c485cf4958d4c6d80 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 3 May 2011 23:01:05 +1000 Subject: [PATCH 45/47] Do not add p1:pushed more than once --- src/mod_ack.erl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod_ack.erl b/src/mod_ack.erl index 02f5ebb1a..68606283f 100644 --- a/src/mod_ack.erl +++ b/src/mod_ack.erl @@ -215,14 +215,15 @@ handle_cast({del, Pid}, State) -> lists:foreach( fun({_, _, {TRef, {From, To, El}}}) -> cancel_timer(TRef), - El1 = xml:append_subtags( - El, [{xmlelement, "x", [{"xmlns", ?NS_P1_PUSHED}], []}]), + El1 = xml:remove_subtags(El, "x", {"xmlns", ?NS_P1_PUSHED}), + El2 = xml:append_subtags( + El1, [{xmlelement, "x", [{"xmlns", ?NS_P1_PUSHED}], []}]), ?DEBUG("Resending message:~n" "** From: ~p~n" "** To: ~p~n" "** El: ~p", - [From, To, El1]), - ejabberd_router:route(From, To, El1) + [From, To, El2]), + ejabberd_router:route(From, To, El2) end, to_list(Pid, State#state.timers)), Timers = delete(Pid, State#state.timers), {noreply, State#state{timers = Timers}}; From 1922bf21f0e945515ab1a41ca81a462e9b1aa55e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 5 May 2011 18:59:33 +1000 Subject: [PATCH 46/47] Do not try to start TLS twice when front-end socket is used --- src/ejabberd_c2s.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index e87128949..2566dec1b 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -246,7 +246,7 @@ init([{SockMod, Socket}, Opts, FSMLimitOpts]) -> false -> Socket1 = if - TLSEnabled -> + TLSEnabled andalso SockMod /= ejabberd_frontend_socket -> SockMod:starttls(Socket, TLSOpts); true -> Socket From 8806fdc1c2f43ebd4a0a69ff89cd70e451424f35 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 9 May 2011 13:43:54 +1000 Subject: [PATCH 47/47] Implement C2S redirection - The feature is based on stream error, see RFC6120, 4.9.3.19 - To enable the feature you must set {redirect, true} in C2S listener section and set global "hostname" option on all nodes in cluster. The hostname must be string in the form as described in the RFC, for example: "foo.org", "foo.org:5222", "1.2.3.4", "[2001:41D0:1:A49b::1]:9222" and so on --- src/ejabberd_c2s.erl | 181 ++++++++++++++++++++++++++-------------- src/ejabberd_c2s.hrl | 1 + src/ejabberd_config.erl | 2 + src/jlib.hrl | 112 ++++++++++++------------- 4 files changed, 176 insertions(+), 120 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 2566dec1b..bc8b087db 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -231,6 +231,12 @@ init([{SockMod, Socket}, Opts, FSMLimitOpts]) -> (_) -> false end, Opts), TLSOpts = [verify_none | TLSOpts1], + Redirect = case lists:keysearch(redirect, 1, Opts) of + {value, {_, true}} -> + true; + _ -> + false + end, IP = case lists:keysearch(frontend_ip, 1, Opts) of {value, {_, IP1}} -> IP1; @@ -265,6 +271,7 @@ init([{SockMod, Socket}, Opts, FSMLimitOpts]) -> access = Access, shaper = Shaper, ip = IP, + redirect = Redirect, fsm_limit_opts = FSMLimitOpts}, {ok, wait_for_stream, StateData, ?C2S_OPEN_TIMEOUT} end; @@ -585,45 +592,55 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> "(~w) Accepted legacy authentication for ~s by ~p", [StateData#state.socket, jlib:jid_to_string(JID), AuthModule]), - SID = {now(), self()}, - Conn = get_conn_type(StateData), - %% Info = [{ip, StateData#state.ip}, {conn, Conn}, - %% {auth_module, AuthModule}], - Res1 = jlib:make_result_iq_reply(El), - Res = setelement(4, Res1, []), - send_element(StateData, Res), - %% ejabberd_sm:open_session( - %% SID, U, StateData#state.server, R, Info), - change_shaper(StateData, JID), - {Fs, Ts} = ejabberd_hooks:run_fold( - roster_get_subscription_lists, - StateData#state.server, - {[], []}, - [U, StateData#state.server]), - LJID = jlib:jid_tolower( - jlib:jid_remove_resource(JID)), - Fs1 = [LJID | Fs], - Ts1 = [LJID | Ts], - PrivList = - ejabberd_hooks:run_fold( - privacy_get_user_list, StateData#state.server, - #userlist{}, - [U, StateData#state.server]), - NewStateData = StateData#state{ - user = U, - resource = R, - jid = JID, - sid = SID, - conn = Conn, - auth_module = AuthModule, - pres_f = ?SETS:from_list(Fs1), - pres_t = ?SETS:from_list(Ts1), - privacy_list = PrivList}, - DebugFlag = ejabberd_hooks:run_fold(c2s_debug_start_hook, - NewStateData#state.server, - false, - [self(), NewStateData]), - maybe_migrate(session_established, NewStateData#state{debug=DebugFlag}); + case need_redirect(StateData#state{user = U}) of + {true, Host} -> + ?INFO_MSG("(~w) Redirecting ~s to ~s", + [StateData#state.socket, + jlib:jid_to_string(JID), Host]), + send_element(StateData, ?SERR_SEE_OTHER_HOST(Host)), + send_trailer(StateData), + {stop, normal, StateData}; + false -> + SID = {now(), self()}, + Conn = get_conn_type(StateData), + Res1 = jlib:make_result_iq_reply(El), + Res = setelement(4, Res1, []), + send_element(StateData, Res), + change_shaper(StateData, JID), + {Fs, Ts} = ejabberd_hooks:run_fold( + roster_get_subscription_lists, + StateData#state.server, + {[], []}, + [U, StateData#state.server]), + LJID = jlib:jid_tolower( + jlib:jid_remove_resource(JID)), + Fs1 = [LJID | Fs], + Ts1 = [LJID | Ts], + PrivList = + ejabberd_hooks:run_fold( + privacy_get_user_list, + StateData#state.server, + #userlist{}, + [U, StateData#state.server]), + NewStateData = + StateData#state{ + user = U, + resource = R, + jid = JID, + sid = SID, + conn = Conn, + auth_module = AuthModule, + pres_f = ?SETS:from_list(Fs1), + pres_t = ?SETS:from_list(Ts1), + privacy_list = PrivList}, + DebugFlag = ejabberd_hooks:run_fold( + c2s_debug_start_hook, + NewStateData#state.server, + false, + [self(), NewStateData]), + maybe_migrate(session_established, + NewStateData#state{debug=DebugFlag}) + end; _ -> ?INFO_MSG( "(~w) Failed legacy authentication for ~s", @@ -715,21 +732,30 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> Mech, ClientIn) of {ok, Props} -> - catch (StateData#state.sockmod):reset_stream( - StateData#state.socket), - send_element(StateData, - {xmlelement, "success", - [{"xmlns", ?NS_SASL}], []}), - U = xml:get_attr_s(username, Props), - AuthModule = xml:get_attr_s(auth_module, Props), - ?INFO_MSG("(~w) Accepted authentication for ~s by ~p", - [StateData#state.socket, U, AuthModule]), - fsm_next_state(wait_for_stream, - StateData#state{ - streamid = new_id(), - authenticated = true, - auth_module = AuthModule, - user = U }); + catch (StateData#state.sockmod):reset_stream( + StateData#state.socket), + U = xml:get_attr_s(username, Props), + AuthModule = xml:get_attr_s(auth_module, Props), + ?INFO_MSG("(~w) Accepted authentication for ~s by ~p", + [StateData#state.socket, U, AuthModule]), + case need_redirect(StateData#state{user = U}) of + {true, Host} -> + ?INFO_MSG("(~w) Redirecting ~s to ~s", + [StateData#state.socket, U, Host]), + send_element(StateData, ?SERR_SEE_OTHER_HOST(Host)), + send_trailer(StateData), + {stop, normal, StateData}; + false -> + send_element(StateData, + {xmlelement, "success", + [{"xmlns", ?NS_SASL}], []}), + fsm_next_state(wait_for_stream, + StateData#state{ + streamid = new_id(), + authenticated = true, + auth_module = AuthModule, + user = U }) + end; {continue, ServerOut, NewSASLState} -> send_element(StateData, {xmlelement, "challenge", @@ -869,20 +895,29 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) -> ClientIn) of {ok, Props} -> catch (StateData#state.sockmod):reset_stream( - StateData#state.socket), - send_element(StateData, - {xmlelement, "success", - [{"xmlns", ?NS_SASL}], []}), + StateData#state.socket), U = xml:get_attr_s(username, Props), AuthModule = xml:get_attr_s(auth_module, Props), ?INFO_MSG("(~w) Accepted authentication for ~s by ~p", [StateData#state.socket, U, AuthModule]), - fsm_next_state(wait_for_stream, - StateData#state{ - streamid = new_id(), - authenticated = true, - auth_module = AuthModule, - user = U}); + case need_redirect(StateData#state{user = U}) of + {true, Host} -> + ?INFO_MSG("(~w) Redirecting ~s to ~s", + [StateData#state.socket, U, Host]), + send_element(StateData, ?SERR_SEE_OTHER_HOST(Host)), + send_trailer(StateData), + {stop, normal, StateData}; + false -> + send_element(StateData, + {xmlelement, "success", + [{"xmlns", ?NS_SASL}], []}), + fsm_next_state(wait_for_stream, + StateData#state{ + streamid = new_id(), + authenticated = true, + auth_module = AuthModule, + user = U}) + end; {continue, ServerOut, NewSASLState} -> send_element(StateData, {xmlelement, "challenge", @@ -3394,3 +3429,21 @@ flash_policy_string() -> ++ ToPortsString ++ "\"/>\n" "\n\0". + +need_redirect(#state{redirect = true, user = User, server = Server}) -> + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + case ejabberd_cluster:get_node({LUser, LServer}) of + Node when node() == Node -> + false; + Node -> + case rpc:call(Node, ejabberd_config, + get_local_option, [hostname], 5000) of + Host when is_list(Host) -> + {true, Host}; + _ -> + false + end + end; +need_redirect(_) -> + false. diff --git a/src/ejabberd_c2s.hrl b/src/ejabberd_c2s.hrl index 9af6b02d5..7889c0de5 100644 --- a/src/ejabberd_c2s.hrl +++ b/src/ejabberd_c2s.hrl @@ -57,6 +57,7 @@ conn = unknown, auth_module = unknown, ip, + redirect = false, aux_fields = [], fsm_limit_opts, lang, diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 1609b447d..848bcf7ca 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -440,6 +440,8 @@ process_term(Term, State) -> State; {max_fsm_queue, N} -> add_option(max_fsm_queue, N, State); + {hostname, Host} -> + add_option(hostname, Host, State); {_Opt, _Val} -> lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end, State, State#state.hosts) diff --git a/src/jlib.hrl b/src/jlib.hrl index a4f8fd0da..7ac220cc0 100644 --- a/src/jlib.hrl +++ b/src/jlib.hrl @@ -206,117 +206,117 @@ ?ERRT_CONFLICT(Lang, "Resource conflict")). --define(STREAM_ERROR(Condition), +-define(STREAM_ERROR(Condition, Cdata), {xmlelement, "stream:error", [], - [{xmlelement, Condition, [{"xmlns", ?NS_STREAMS}], []}]}). + [{xmlelement, Condition, [{"xmlns", ?NS_STREAMS}], + [{xmlcdata, Cdata}]}]}). -define(SERR_BAD_FORMAT, - ?STREAM_ERROR("bad-format")). + ?STREAM_ERROR("bad-format", "")). -define(SERR_BAD_NAMESPACE_PREFIX, - ?STREAM_ERROR("bad-namespace-prefix")). + ?STREAM_ERROR("bad-namespace-prefix", "")). -define(SERR_CONFLICT, - ?STREAM_ERROR("conflict")). + ?STREAM_ERROR("conflict", "")). -define(SERR_CONNECTION_TIMEOUT, - ?STREAM_ERROR("connection-timeout")). + ?STREAM_ERROR("connection-timeout", "")). -define(SERR_HOST_GONE, - ?STREAM_ERROR("host-gone")). + ?STREAM_ERROR("host-gone", "")). -define(SERR_HOST_UNKNOWN, - ?STREAM_ERROR("host-unknown")). + ?STREAM_ERROR("host-unknown", "")). -define(SERR_IMPROPER_ADDRESSING, - ?STREAM_ERROR("improper-addressing")). + ?STREAM_ERROR("improper-addressing", "")). -define(SERR_INTERNAL_SERVER_ERROR, - ?STREAM_ERROR("internal-server-error")). + ?STREAM_ERROR("internal-server-error", "")). -define(SERR_INVALID_FROM, - ?STREAM_ERROR("invalid-from")). + ?STREAM_ERROR("invalid-from", "")). -define(SERR_INVALID_ID, - ?STREAM_ERROR("invalid-id")). + ?STREAM_ERROR("invalid-id", "")). -define(SERR_INVALID_NAMESPACE, - ?STREAM_ERROR("invalid-namespace")). + ?STREAM_ERROR("invalid-namespace", "")). -define(SERR_INVALID_XML, - ?STREAM_ERROR("invalid-xml")). + ?STREAM_ERROR("invalid-xml", "")). -define(SERR_NOT_AUTHORIZED, - ?STREAM_ERROR("not-authorized")). + ?STREAM_ERROR("not-authorized", "")). -define(SERR_POLICY_VIOLATION, - ?STREAM_ERROR("policy-violation")). + ?STREAM_ERROR("policy-violation", "")). -define(SERR_REMOTE_CONNECTION_FAILED, - ?STREAM_ERROR("remote-connection-failed")). + ?STREAM_ERROR("remote-connection-failed", "")). -define(SERR_RESOURSE_CONSTRAINT, - ?STREAM_ERROR("resource-constraint")). + ?STREAM_ERROR("resource-constraint", "")). -define(SERR_RESTRICTED_XML, - ?STREAM_ERROR("restricted-xml")). -% TODO: include hostname or IP --define(SERR_SEE_OTHER_HOST, - ?STREAM_ERROR("see-other-host")). + ?STREAM_ERROR("restricted-xml", "")). +-define(SERR_SEE_OTHER_HOST(Host), + ?STREAM_ERROR("see-other-host", Host)). -define(SERR_SYSTEM_SHUTDOWN, - ?STREAM_ERROR("system-shutdown")). + ?STREAM_ERROR("system-shutdown", "")). -define(SERR_UNSUPPORTED_ENCODING, - ?STREAM_ERROR("unsupported-encoding")). + ?STREAM_ERROR("unsupported-encoding", "")). -define(SERR_UNSUPPORTED_STANZA_TYPE, - ?STREAM_ERROR("unsupported-stanza-type")). + ?STREAM_ERROR("unsupported-stanza-type", "")). -define(SERR_UNSUPPORTED_VERSION, - ?STREAM_ERROR("unsupported-version")). + ?STREAM_ERROR("unsupported-version", "")). -define(SERR_XML_NOT_WELL_FORMED, - ?STREAM_ERROR("xml-not-well-formed")). + ?STREAM_ERROR("xml-not-well-formed", "")). %-define(SERR_, -% ?STREAM_ERROR("")). +% ?STREAM_ERROR("", "")). --define(STREAM_ERRORT(Condition, Lang, Text), +-define(STREAM_ERRORT(Condition, Cdata, Lang, Text), {xmlelement, "stream:error", [], - [{xmlelement, Condition, [{"xmlns", ?NS_STREAMS}], []}, + [{xmlelement, Condition, [{"xmlns", ?NS_STREAMS}], + [{xmlcdata, Cdata}]}, {xmlelement, "text", [{"xml:lang", Lang}, {"xmlns", ?NS_STREAMS}], [{xmlcdata, translate:translate(Lang, Text)}]}]}). -define(SERRT_BAD_FORMAT(Lang, Text), - ?STREAM_ERRORT("bad-format", Lang, Text)). + ?STREAM_ERRORT("bad-format", "", Lang, Text)). -define(SERRT_BAD_NAMESPACE_PREFIX(Lang, Text), - ?STREAM_ERRORT("bad-namespace-prefix", Lang, Text)). + ?STREAM_ERRORT("bad-namespace-prefix", "", Lang, Text)). -define(SERRT_CONFLICT(Lang, Text), - ?STREAM_ERRORT("conflict", Lang, Text)). + ?STREAM_ERRORT("conflict", "", Lang, Text)). -define(SERRT_CONNECTION_TIMEOUT(Lang, Text), - ?STREAM_ERRORT("connection-timeout", Lang, Text)). + ?STREAM_ERRORT("connection-timeout", "", Lang, Text)). -define(SERRT_HOST_GONE(Lang, Text), - ?STREAM_ERRORT("host-gone", Lang, Text)). + ?STREAM_ERRORT("host-gone", "", Lang, Text)). -define(SERRT_HOST_UNKNOWN(Lang, Text), - ?STREAM_ERRORT("host-unknown", Lang, Text)). + ?STREAM_ERRORT("host-unknown", "", Lang, Text)). -define(SERRT_IMPROPER_ADDRESSING(Lang, Text), - ?STREAM_ERRORT("improper-addressing", Lang, Text)). + ?STREAM_ERRORT("improper-addressing", "", Lang, Text)). -define(SERRT_INTERNAL_SERVER_ERROR(Lang, Text), - ?STREAM_ERRORT("internal-server-error", Lang, Text)). + ?STREAM_ERRORT("internal-server-error", "", Lang, Text)). -define(SERRT_INVALID_FROM(Lang, Text), - ?STREAM_ERRORT("invalid-from", Lang, Text)). + ?STREAM_ERRORT("invalid-from", "", Lang, Text)). -define(SERRT_INVALID_ID(Lang, Text), - ?STREAM_ERRORT("invalid-id", Lang, Text)). + ?STREAM_ERRORT("invalid-id", "", Lang, Text)). -define(SERRT_INVALID_NAMESPACE(Lang, Text), - ?STREAM_ERRORT("invalid-namespace", Lang, Text)). + ?STREAM_ERRORT("invalid-namespace", "", Lang, Text)). -define(SERRT_INVALID_XML(Lang, Text), - ?STREAM_ERRORT("invalid-xml", Lang, Text)). + ?STREAM_ERRORT("invalid-xml", "", Lang, Text)). -define(SERRT_NOT_AUTHORIZED(Lang, Text), - ?STREAM_ERRORT("not-authorized", Lang, Text)). + ?STREAM_ERRORT("not-authorized", "", Lang, Text)). -define(SERRT_POLICY_VIOLATION(Lang, Text), - ?STREAM_ERRORT("policy-violation", Lang, Text)). + ?STREAM_ERRORT("policy-violation", "", Lang, Text)). -define(SERRT_REMOTE_CONNECTION_FAILED(Lang, Text), - ?STREAM_ERRORT("remote-connection-failed", Lang, Text)). + ?STREAM_ERRORT("remote-connection-failed", "", Lang, Text)). -define(SERRT_RESOURSE_CONSTRAINT(Lang, Text), - ?STREAM_ERRORT("resource-constraint", Lang, Text)). + ?STREAM_ERRORT("resource-constraint", "", Lang, Text)). -define(SERRT_RESTRICTED_XML(Lang, Text), - ?STREAM_ERRORT("restricted-xml", Lang, Text)). -% TODO: include hostname or IP --define(SERRT_SEE_OTHER_HOST(Lang, Text), - ?STREAM_ERRORT("see-other-host", Lang, Text)). + ?STREAM_ERRORT("restricted-xml", "", Lang, Text)). +-define(SERRT_SEE_OTHER_HOST(Host, Lang, Text), + ?STREAM_ERRORT("see-other-host", Host, Lang, Text)). -define(SERRT_SYSTEM_SHUTDOWN(Lang, Text), - ?STREAM_ERRORT("system-shutdown", Lang, Text)). + ?STREAM_ERRORT("system-shutdown", "", Lang, Text)). -define(SERRT_UNSUPPORTED_ENCODING(Lang, Text), - ?STREAM_ERRORT("unsupported-encoding", Lang, Text)). + ?STREAM_ERRORT("unsupported-encoding", "", Lang, Text)). -define(SERRT_UNSUPPORTED_STANZA_TYPE(Lang, Text), - ?STREAM_ERRORT("unsupported-stanza-type", Lang, Text)). + ?STREAM_ERRORT("unsupported-stanza-type", "", Lang, Text)). -define(SERRT_UNSUPPORTED_VERSION(Lang, Text), - ?STREAM_ERRORT("unsupported-version", Lang, Text)). + ?STREAM_ERRORT("unsupported-version", "", Lang, Text)). -define(SERRT_XML_NOT_WELL_FORMED(Lang, Text), - ?STREAM_ERRORT("xml-not-well-formed", Lang, Text)). + ?STREAM_ERRORT("xml-not-well-formed", "", Lang, Text)). %-define(SERRT_(Lang, Text), -% ?STREAM_ERRORT("", Lang, Text)). +% ?STREAM_ERRORT("", "", Lang, Text)). -record(jid, {user, server, resource,