Simple Download Monitor - Version 0.05

Version Description

  • First intentional public release.
Download this release

Release Info

Developer pepak.net
Plugin Icon 128x128 Simple Download Monitor
Version 0.05
Comparing to
See all releases

Version 0.05

css/sdmon.css ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ #sdmon .sdmon-rownum { width: 3ex; text-align: right; }
2
+ #sdmon .sdmon-filename { }
3
+ #sdmon .sdmon-count { text-align: right; }
4
+ #sdmon .sdmon-date { width: 24ex; text-align: center; }
5
+ #sdmon .sdmon-nonex { width: 5ex; text-align: center; }
6
+ #sdmon .sdmon-ipaddr { }
7
+ #sdmon .sdmon-referer { }
8
+ #sdmon .sdmon-username { }
9
+ #sdmon th {text-align: center; }
10
+ #sdmon th, #sdmon td { padding-left: 1ex; padding-right: 1ex; }
lang/cs_CZ.mo ADDED
Binary file
lang/cs_CZ.po ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Simple Download Monitor v0.04\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2009-10-28 09:08+0100\n"
6
+ "PO-Revision-Date: \n"
7
+ "Last-Translator: pepak <pepak@pepak.net>\n"
8
+ "Language-Team: Pepak <pepak@pepak.net>\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Poedit-Language: Czech\n"
13
+ "X-Poedit-Country: CZECH REPUBLIC\n"
14
+ "X-Poedit-SourceCharset: utf-8\n"
15
+ "X-Poedit-KeywordsList: _e;__\n"
16
+ "X-Poedit-Basepath: ..\n"
17
+ "X-Poedit-SearchPath-0: ..\n"
18
+
19
+ #: ../sdmon/simple-download-monitor.php:209
20
+ #: ../sdmon/simple-download-monitor.php:479
21
+ msgid "Simple Download Monitor options"
22
+ msgstr "Simple Download Monitor - nastavení"
23
+
24
+ #: ../sdmon/simple-download-monitor.php:210
25
+ msgid "Allowed directories"
26
+ msgstr "Povolené adresáře"
27
+
28
+ #: ../sdmon/simple-download-monitor.php:211
29
+ msgid "Only requested files whose full names (relative to document root) start with this regular expression will be processed. It is strongly recommended to place all downloadable files (and ONLY downloadable files) into a designated directory and then placing that directory's name followed by a slash here. It is possible to use the power of PREG to allow multiple directories, but make sure there are ONLY files which you are comfortable with malicious users downloading. Do not EVER allow directories which contain PHP files here! That could lead to disclosure of sensitive data, including username and password used to connect to WordPress database."
30
+ msgstr "Zpracovávány budou pouze soubory, jejichž plná jména (relativní vůči kořenovému adresáři webu) začínají tímto regulárním výrazem. Silně doporučuji umístit všechny stažitelné soubory (a JENOM stažitelné soubory) do jednoho určeného adresáře a vepsat sem název tohoto adresáře zakončený lomítkem. Lze také využít všech možností, které dává PREG, pro povolení více adresářů, ale dejte si pozor, ať v nich jsou JEDINĚ soubory, u kterých vám nevadí, když si je stáhne útočník. NIKDY do těchto adresářů neukládejte žádné PHP soubory! To by mohlo vést k zveřejnění citlivých dat, včetně uživatelského jména a hesla pro připojení k databázi."
31
+
32
+ #: ../sdmon/simple-download-monitor.php:212
33
+ msgid "Default value is <code>files/</code>, which only allows download from /files directory (the leading <code>/</code> is implicit)."
34
+ msgstr "Výchozí hodnota je <code>files/</code>, která dovolí stahovat pouze soubory z adresáře /files (úvodní <code>/</code> je dosazeno automaticky)."
35
+
36
+ #: ../sdmon/simple-download-monitor.php:214
37
+ msgid "Allowed extensions"
38
+ msgstr "Povolené přípony"
39
+
40
+ #: ../sdmon/simple-download-monitor.php:215
41
+ msgid "Only files with extensions matching this regular expressions will be processed. This is another important security value. Make sure you only add extensions which are safe for malicious users to have, e.g. archives and possibly images. Do NOT use any expression that could allow a user to download PHP files, even if you think it safe given the Allowed Directories option above."
42
+ msgstr "Zpracovávány budou pouze soubory, jejichž přípony odpovídají tomuto regulárnímu výrazu. Jde o další důležitý bezpečnostní prvek. Dejte si pozor, ať jsou zde uvedeny pouze takové přípony, které nemohou být zneužity útočníky, tzn. komprimované archívy a případně obrázky. NEPOUŽÍVEJTE výrazy, které by mohly uživateli dovolit download PHP souborů, ani kdyby tyto soubory vylučovalo nastavení \"Povolené adresáře\" výše."
43
+
44
+ #: ../sdmon/simple-download-monitor.php:216
45
+ msgid "Default value is <code>zip|rar|7z</code> which only allows download of files ending with <code>.zip</code>, <code>.rar</code> and <code>.7z</code> (the leading <code>.</code> is implicit)."
46
+ msgstr "Výchozí hodnota je <code>zip|rar|7z</code>, která povolí pouze stahování souborů s příponou <code>.zip</code>, <code>.rar</code> a <code>.7z</code> (úvodní <code>.</code> je dosazena automaticky)."
47
+
48
+ #: ../sdmon/simple-download-monitor.php:218
49
+ msgid "Store detailed logs?"
50
+ msgstr "Ukládat detailní záznamy?"
51
+
52
+ #: ../sdmon/simple-download-monitor.php:219
53
+ msgid "If detailed logs are allowed, various information (including exact time of download, user's IP address, referrer etc.) is stored. This can fill your database quickly if you have only a little space or a lot of popular downloads. Otherwise just the total numbers of downloads are stored, consuming significantly less space."
54
+ msgstr "Pokud je tato volba zapnuta, ukládají se detailní informace (jako přesný čas, IP adresa uživatele nebo referer) o každém downloadu. To může rychle zahltit databázi, pokud máte jen málo prostoru nebo populární downloady. Normálně se ukládá jen celkový počet stažení, který zabírá podstatně méně místa."
55
+
56
+ #: ../sdmon/simple-download-monitor.php:220
57
+ msgid "Use detailed statistics."
58
+ msgstr "Používat detailní statistiky"
59
+
60
+ #: ../sdmon/simple-download-monitor.php:221
61
+ msgid "Update settings"
62
+ msgstr "Uložit nastavení"
63
+
64
+ #: ../sdmon/simple-download-monitor.php:326
65
+ msgid "First"
66
+ msgstr "První"
67
+
68
+ #: ../sdmon/simple-download-monitor.php:327
69
+ msgid "Previous"
70
+ msgstr "Předchozí"
71
+
72
+ #: ../sdmon/simple-download-monitor.php:332
73
+ msgid "Next"
74
+ msgstr "Další"
75
+
76
+ #: ../sdmon/simple-download-monitor.php:333
77
+ msgid "Last"
78
+ msgstr "Poslední"
79
+
80
+ #: ../sdmon/simple-download-monitor.php:348
81
+ #: ../sdmon/simple-download-monitor.php:411
82
+ #: ../sdmon/simple-download-monitor.php:479
83
+ #: ../sdmon/simple-download-monitor.php:480
84
+ msgid "Simple Download Monitor"
85
+ msgstr "Simple Download Monitor"
86
+
87
+ #: ../sdmon/simple-download-monitor.php:349
88
+ msgid "Nonexistent downloads"
89
+ msgstr "Neexistující soubory"
90
+
91
+ #: ../sdmon/simple-download-monitor.php:349
92
+ msgid "All downloads"
93
+ msgstr "Všechny downloady"
94
+
95
+ #: ../sdmon/simple-download-monitor.php:350
96
+ msgid "Show all downloads"
97
+ msgstr "Zobrazit všechny soubory"
98
+
99
+ #: ../sdmon/simple-download-monitor.php:350
100
+ msgid "Show nonexistent downloads"
101
+ msgstr "Zobrazit neexistující soubory"
102
+
103
+ #: ../sdmon/simple-download-monitor.php:361
104
+ msgid "Filename"
105
+ msgstr "Název souboru"
106
+
107
+ #: ../sdmon/simple-download-monitor.php:362
108
+ msgid "Download count"
109
+ msgstr "Počet stažení"
110
+
111
+ #: ../sdmon/simple-download-monitor.php:363
112
+ msgid "Last date"
113
+ msgstr "Poslední datum"
114
+
115
+ #: ../sdmon/simple-download-monitor.php:412
116
+ #, php-format
117
+ msgid "Detailed data for <strong>%s</strong>:"
118
+ msgstr "Detailní data pro <strong>%s</strong>:"
119
+
120
+ #: ../sdmon/simple-download-monitor.php:413
121
+ #, php-format
122
+ msgid "Total number of downloads: <strong>%d</strong>."
123
+ msgstr "Celkový počet stažení: <strong>%d</strong>."
124
+
125
+ #: ../sdmon/simple-download-monitor.php:425
126
+ msgid "Date"
127
+ msgstr "Datum"
128
+
129
+ #: ../sdmon/simple-download-monitor.php:426
130
+ msgid "IP address"
131
+ msgstr "IP adresa"
132
+
133
+ #: ../sdmon/simple-download-monitor.php:427
134
+ msgid "Referer"
135
+ msgstr "Referer"
136
+
137
+ #: ../sdmon/simple-download-monitor.php:428
138
+ msgid "Username"
139
+ msgstr "Uživatel"
140
+
141
+ #: ../sdmon/simple-download-monitor.php:457
142
+ msgid "Return to full list."
143
+ msgstr "Návrat do úplného seznamu"
144
+
readme.txt ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Plugin Name ===
2
+ Contributors: Pepak
3
+ Donate link:
4
+ Tags: files, counter, count, tracking, download monitor, monitor, downloads, download
5
+ Requires at least: 2.8.0
6
+ Tested up to: 2.8.4
7
+ Stable tag: 0.05
8
+
9
+ Count the number of downloads without having to maintain a comprehensive download page.
10
+
11
+ == Description ==
12
+
13
+ I wrote Simple Download Monitor because I wanted to monitor the number of downloads of my
14
+ files without having to maintain any kind of database or making any special download links.
15
+ I just wanted to upload a file to a designated directory using FTP, provide a direct link
16
+ to it and once in a while check the number of downloads. And this is pretty much what
17
+ Simple Download Monitor does, with some slight additions, such as recording referers and
18
+ username of people who download my files.
19
+
20
+ == Installation ==
21
+
22
+ 1. Create a subdirectory in your '/wp-content/plugins/' directory and extract the plugin
23
+ there. The plugin subdirectory can be anything you like - I use 'simple-download-monitor',
24
+ but the plugin should accept any name.
25
+ 1. Activate the plugin through the 'Plugins' menu in WordPress.
26
+ 1. You will see a 'Simple Download Monitor' item in your 'Settings' menu. You can enter
27
+ three options there:
28
+ * Allowed directories. The plugin could potentially be a huge security hole because it
29
+ could be used to download source files of your site (e.g. 'config.php' - you definitely
30
+ don't want to allow that!) This option restricts Simple Download Monitor to directories
31
+ matching a regular expression. The default value of 'files/' means that Simple Download
32
+ Monitor will only allow download of files in the '/files' directory and its subdirectories.
33
+ * Allowed extensions. Much like 'Allowed directories', allowed extensions protect your
34
+ site's files from unwanted downloads. It is a regular expression too and it is recommended
35
+ to only place "safe" extensions such as 'zip' or 'jpg' here. Do not EVER allow 'php'
36
+ extension, either directly or through wildcard (such as '.*' - that is a BIG NO-NO!).
37
+ * Store detailed info. If this option is checked, detailed information about each download
38
+ (such as referer, user's IP address or name, and date of download) is stored. This could
39
+ fill your database quickly if you have a well-visited site so you can turn detailed info
40
+ off and only keep the number of downloads and the date of last download.
41
+ 1. The last step involves editing the '.htaccess' file. The default '.htaccess' skips default
42
+ WordPress processing for existing files, which means that direct-linked files would get
43
+ downloaded directly, without Simple Download Monitor ever learning about it. You need to
44
+ modify the '.htaccess' file so that downloads are passed through Simple Download Monitor.
45
+ This is easy enough to do: Open your '.htaccess' file and locate line
46
+ `RewriteCond %{REQUEST_FILENAME} !-f`
47
+ Add this line directly above it:
48
+ `RewriteRule ^(files/.*) /index.php?sdmon=$1 [L]`
49
+ (replace 'files/' with your download directory).
50
+
51
+ == Frequently Asked Questions ==
52
+
53
+ = Where are the frequently asked questions?
54
+
55
+ Nobody asked any yet.
56
+
57
+ == Screenshots ==
58
+
59
+ 1. Administrative options
60
+ 2. The main statistics page
61
+ 3. Detailed statistics for a file
62
+
63
+ == Changelog ==
64
+
65
+ = 0.05 =
66
+ * First intentional public release.
67
+
68
+ = 0.04 =
69
+ * Accidental premature public release due to my unfamiliarity with WordPress plugin repository.
screenshot-1.png ADDED
Binary file
screenshot-2.png ADDED
Binary file
screenshot-3.png ADDED
Binary file
sdmon.css ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ #sdmon .sdmon-rownum { width: 3ex; text-align: right; }
2
+ #sdmon .sdmon-filename { }
3
+ #sdmon .sdmon-count { text-align: right; }
4
+ #sdmon .sdmon-date { width: 24ex; text-align: center; }
5
+ #sdmon .sdmon-nonex { width: 5ex; text-align: center; }
6
+ #sdmon .sdmon-ipaddr { }
7
+ #sdmon .sdmon-referer { }
8
+ #sdmon .sdmon-username { }
9
+ #sdmon th {text-align: center; }
10
+ #sdmon th, #sdmon td { padding-left: 1ex; padding-right: 1ex; }
simple-download-monitor.php ADDED
@@ -0,0 +1,501 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Plugin Name: Simple Download Monitor
5
+ Plugin URI: http://www.pepak.net/wordpress/simple-download-monitor-plugin
6
+ Description: Count the number of downloads without having to maintain a comprehensive download page.
7
+ Version: 0.05
8
+ Author: Pepak
9
+ Author URI: http://www.pepak.net
10
+ */
11
+
12
+ /* Copyright 2009 Pepak (email: wordpress@pepak.net)
13
+
14
+ This program is free software; you can redistribute it and/or modify
15
+ it under the terms of the GNU General Public License as published by
16
+ the Free Software Foundation; either version 2 of the License, or
17
+ (at your option) any later version.
18
+
19
+ This program is distributed in the hope that it will be useful,
20
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
+ GNU General Public License for more details.
23
+
24
+ You should have received a copy of the GNU General Public License
25
+ along with this program; if not, write to the Free Software
26
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
+ */
28
+
29
+ if (!class_exists('SimpleDownloadMonitor'))
30
+ {
31
+ class SimpleDownloadMonitor
32
+ {
33
+
34
+ const VERSION = '0.05';
35
+ const PREFIX = 'sdmon_';
36
+ const PREG_DELIMITER = '`';
37
+ const GET_PARAM = 'sdmon';
38
+ const RECORDS_PER_PAGE = 20;
39
+
40
+ protected $plugin_url = '';
41
+ protected $plugin_dir = '';
42
+ protected $plugin_dir_relative = '';
43
+
44
+ public function SimpleDownloadMonitor()
45
+ {
46
+ $this->plugin_url = WP_PLUGIN_URL . '/' . dirname(plugin_basename(__FILE__));
47
+ $this->plugin_dir = WP_PLUGIN_DIR . '/' . dirname(plugin_basename(__FILE__));
48
+ if (strpos($this->plugin_dir, ABSPATH) === 0)
49
+ $this->plugin_dir_relative = substr($this->plugin_dir, strlen(ABSPATH));
50
+ else
51
+ $this->plugin_dir_relative = $this->plugin_dir;
52
+ register_activation_hook(__FILE__, array('SimpleDownloadMonitor', 'Install'));
53
+ add_action('init', array(&$this, 'ActionInit'));
54
+ add_action('admin_menu', 'SimpleDownloadMonitor_BuildAdminMenu');
55
+ }
56
+
57
+ public static function Install()
58
+ {
59
+ global $wpdb;
60
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
61
+ $table_downloads = $wpdb->prefix . self::PREFIX . 'downloads';
62
+ $sql = "CREATE TABLE ${table_downloads} (
63
+ id INTEGER NOT NULL AUTO_INCREMENT,
64
+ filename VARCHAR(1024) NOT NULL,
65
+ download_count INTEGER NOT NULL,
66
+ last_date TIMESTAMP NOT NULL,
67
+ file_exists TINYINT,
68
+ PRIMARY KEY id (id),
69
+ KEY download_count (download_count),
70
+ KEY last_date (last_date)
71
+ );";
72
+ dbDelta($sql);
73
+ $table_details = $wpdb->prefix . self::PREFIX . 'details';
74
+ $sql = "CREATE TABLE ${table_details} (
75
+ id INTEGER NOT NULL AUTO_INCREMENT,
76
+ download INTEGER NOT NULL,
77
+ download_date TIMESTAMP NOT NULL,
78
+ ip VARCHAR(64) NOT NULL,
79
+ referer TEXT,
80
+ userid INTEGER,
81
+ username VARCHAR(64),
82
+ PRIMARY KEY id (id),
83
+ KEY download (download),
84
+ KEY download_date (download_date)
85
+ );";
86
+ dbDelta($sql);
87
+ update_option(self::PREFIX . 'table_downloads', $table_downloads);
88
+ update_option(self::PREFIX . 'table_details', $table_details);
89
+ update_option(self::PREFIX . 'version', self::VERSION);
90
+ add_option(self::PREFIX . 'directories', 'files/');
91
+ add_option(self::PREFIX . 'extensions', 'zip|rar|7z');
92
+ add_option(self::PREFIX . 'detailed', '0');
93
+ }
94
+
95
+ protected function table_downloads()
96
+ {
97
+ static $table = null;
98
+ if ($table == null)
99
+ $table = get_option(self::PREFIX . 'table_downloads');
100
+ return $table;
101
+ }
102
+
103
+ protected function table_details()
104
+ {
105
+ static $table = null;
106
+ if ($table == null)
107
+ $table = get_option(self::PREFIX . 'table_details');
108
+ return $table;
109
+ }
110
+
111
+ public function Download($filename)
112
+ {
113
+ global $wpdb, $user_login, $user_ID;
114
+ // Normalize the filename
115
+ $fullfilename = realpath(ABSPATH . '/' . $filename);
116
+ $relfilename = substr($fullfilename, strlen(ABSPATH));
117
+ $relfilename = strtr($relfilename, '\\', '/');
118
+ $exists = (file_exists($fullfilename) AND !is_dir($fullfilename)) ? 1 : 0;
119
+ // Store uncorrected request name to database for security/mistake review
120
+ $downloads = $this->table_downloads();
121
+ $id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ${downloads} WHERE filename=%s", $filename));
122
+ if ($id)
123
+ {
124
+ $sql = "UPDATE ${downloads} SET download_count=download_count+1, last_date=NOW(), file_exists=%d WHERE id=%d";
125
+ $wpdb->query($wpdb->prepare($sql, $exists, $id));
126
+ }
127
+ else
128
+ {
129
+ $sql = "INSERT INTO ${downloads} (filename, download_count, last_date, file_exists) VALUES (%s, 1, NOW(), %d)";
130
+ $wpdb->query($wpdb->prepare($sql, $filename, $exists));
131
+ $id = $wpdb->insert_id;
132
+ }
133
+ // If details are requested, store them as well
134
+ if (intval(get_option(self::PREFIX . 'detailed')))
135
+ {
136
+ $details = $this->table_details();
137
+ $sql = "INSERT INTO ${details} (download, download_date, ip, referer, username, userid) VALUES (%d, NOW(), %s, %s, %s, %d)";
138
+ get_currentuserinfo();
139
+ $userid = $user_ID ? $user_ID : null;
140
+ $username = $user_login ? $user_login : null;
141
+ $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
142
+ if (!$username AND isset($_COOKIE['comment_author_'.COOKIEHASH]))
143
+ $username = utf8_encode($_COOKIE['comment_author_'.COOKIEHASH]);
144
+ $wpdb->query($wpdb->prepare($sql, $id, $_SERVER['REMOTE_ADDR'], $referer, $username, $userid));
145
+ }
146
+ // Make sure the file is available for download
147
+ if (!$exists)
148
+ return FALSE;
149
+ $dirregexp = self::PREG_DELIMITER . '^' . get_option(self::PREFIX . 'directories') . self::PREG_DELIMITER;
150
+ if (!preg_match($dirregexp, $relfilename))
151
+ return FALSE;
152
+ $extregexp = self::PREG_DELIMITER . '\\.' . get_option(self::PREFIX . 'extensions') . '$' . self::PREG_DELIMITER;
153
+ if (!preg_match($extregexp, $relfilename))
154
+ return FALSE;
155
+ // Generate proper headers
156
+ if (function_exists('finfo_open'))
157
+ {
158
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
159
+ $mimetype = finfo_file($finfo, $fullfilename);
160
+ }
161
+ elseif (function_exists('mime_content_type'))
162
+ $mimetype = mime_content_type($fullfilename);
163
+ else
164
+ $mimetype = 'application/octet-stream';
165
+ header('Content-type: ' . $mimetype);
166
+ header('Content-disposition: attachment; filename=' . basename($fullfilename));
167
+ header('Content-size: ' . filesize($fullfilename));
168
+ // Send the file to user.
169
+ $fp = fopen($fullfilename, 'rb');
170
+ fpassthru($fp);
171
+ // Successful end
172
+ return TRUE;
173
+ }
174
+
175
+ public function ActionInit() {
176
+ // Function is called in 'init' hook. It checks for download and if so, stops normal WordPress processing
177
+ // and replaces it with its monitoring functions.
178
+ $currentLocale = get_locale();
179
+ if(!empty($currentLocale))
180
+ {
181
+ $moFile = $this->plugin_dir . "/lang/" . $currentLocale . ".mo";
182
+ if(@file_exists($moFile) && is_readable($moFile))
183
+ load_textdomain('simple-download-monitor', $moFile);
184
+ }
185
+ //load_plugin_textdomain('simple-download-monitor', $this->plugin_dir . '/lang');
186
+ if (isset($_GET[self::GET_PARAM]) && ($filename = $_GET[self::GET_PARAM]))
187
+ {
188
+ if ($this->Download($filename))
189
+ die();
190
+ else
191
+ wp_redirect(get_option('site_url'));
192
+ }
193
+ }
194
+
195
+ public function AdminPanel()
196
+ {
197
+ // Function draws the admin panel.
198
+ // First, post any modified options
199
+ if (isset($_POST['SimpleDownloadMonitor_Submit']))
200
+ {
201
+ // Read options from the form
202
+ $directories = strval($_POST[self::PREFIX . 'directories']);
203
+ $extensions = strval($_POST[self::PREFIX . 'extensions']);
204
+ $detailed = intval($_POST[self::PREFIX . 'detailed']);
205
+ // Remove slashes if necessary
206
+ if (get_magic_quotes_gpc())
207
+ {
208
+ $directories = stripslashes($directories);
209
+ $extensions = stripslashes($extensions);
210
+ }
211
+ // Escape the delimiter
212
+ list($directories, $extensions) = str_replace(self::PREG_DELIMITER, '\\'.self::PREG_DELIMITER, array($directories, $extensions));
213
+ // Write the changes to database
214
+ update_option(self::PREFIX . 'directories', $directories);
215
+ update_option(self::PREFIX . 'extensions', $extensions);
216
+ update_option(self::PREFIX . 'detailed', $detailed);
217
+ }
218
+ // Load options from the database
219
+ $directories = get_option(self::PREFIX . 'directories');
220
+ $extensions = get_option(self::PREFIX . 'extensions');
221
+ $detailed = get_option(self::PREFIX . 'detailed');
222
+ // Build the form
223
+ ?>
224
+ <div class="wrap">
225
+ <form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
226
+ <h2><?php echo __('Simple Download Monitor options', 'simple-download-monitor'); ?></h2>
227
+ <h3><?php echo __('Allowed directories', 'simple-download-monitor'); ?></h3>
228
+ <p><?php echo __("Only requested files whose full names (relative to document root) start with this regular expression will be processed. It is strongly recommended to place all downloadable files (and ONLY downloadable files) into a designated directory and then placing that directory's name followed by a slash here. It is possible to use the power of PREG to allow multiple directories, but make sure there are ONLY files which you are comfortable with malicious users downloading. Do not EVER allow directories which contain PHP files here! That could lead to disclosure of sensitive data, including username and password used to connect to WordPress database.", 'simple-download-monitor'); ?></p>
229
+ <p><?php echo __("Default value is <code>files/</code>, which only allows download from /files directory (the leading <code>/</code> is implicit).", 'simple-download-monitor'); ?></p>
230
+ <p><input type="text" name="<?php echo self::PREFIX; ?>directories" value="<?php echo attribute_escape($directories); ?>" /></p>
231
+ <h3><?php echo __('Allowed extensions', 'simple-download-monitor'); ?></h3>
232
+ <p><?php echo __('Only files with extensions matching this regular expressions will be processed. This is another important security value. Make sure you only add extensions which are safe for malicious users to have, e.g. archives and possibly images. Do NOT use any expression that could allow a user to download PHP files, even if you think it safe given the Allowed Directories option above.', 'simple-download-monitor'); ?></p>
233
+ <p><?php echo __("Default value is <code>zip|rar|7z</code> which only allows download of files ending with <code>.zip</code>, <code>.rar</code> and <code>.7z</code> (the leading <code>.</code> is implicit).", 'simple-download-monitor'); ?></p>
234
+ <p><input type="text" name="<?php echo self::PREFIX; ?>extensions" value="<?php echo attribute_escape($extensions); ?>" /></p>
235
+ <h3><?php echo __("Store detailed logs?", 'simple-download-monitor'); ?></h3>
236
+ <p><?php echo __("If detailed logs are allowed, various information (including exact time of download, user's IP address, referrer etc.) is stored. This can fill your database quickly if you have only a little space or a lot of popular downloads. Otherwise just the total numbers of downloads are stored, consuming significantly less space.", 'simple-download-monitor'); ?></p>
237
+ <p><label for="<?php echo self::PREFIX; ?>detailed"><input type="checkbox" name="<?php echo self::PREFIX; ?>detailed" value="1" <?php if ($detailed) echo 'checked="checked" '; ?>/> <?php echo __('Use detailed statistics.', 'simple-download-monitor'); ?></label></p>
238
+ <div class="submit"><input type="submit" name="SimpleDownloadMonitor_Submit" value="<?php echo __("Update settings", 'simple-download-monitor') ?>" /></div>
239
+ </form>
240
+ </div><?php
241
+ }
242
+
243
+ public function ToolsPanel()
244
+ {
245
+ $download = isset($_GET['download']) ? intval($_GET['download']) : 0;
246
+ $from = isset($_GET['from']) ? intval($_GET['from']) : 0;
247
+ $order = isset($_GET['order']) ? $_GET['order'] : '';
248
+ $flags = isset($_GET['flags']) ? intval($_GET['flags']) : 0;
249
+ $detailed = get_option(self::PREFIX . 'detailed');
250
+ $options = array('download' => $download, 'from' => $from, 'order' => $order, 'flags' => $flags);
251
+ if ($detailed && $download)
252
+ $this->DetailedDownloadList($options);
253
+ else
254
+ $this->DownloadList($options);
255
+ }
256
+
257
+ const ORDER_NAME = 'name';
258
+ const ORDER_COUNT = 'count';
259
+ const ORDER_DATE = 'date';
260
+ const ORDER_IP = 'ip';
261
+ const ORDER_REFERER = 'referer';
262
+ const ORDER_USER = 'user';
263
+
264
+ protected function GetOrderBy($order = '')
265
+ {
266
+ static $orders = array(
267
+ self::ORDER_NAME => 'filename',
268
+ self::ORDER_COUNT => 'download_count DESC, filename',
269
+ self::ORDER_DATE => 'last_date DESC, filename',
270
+ );
271
+ $result = isset($orders[$order]) ? $orders[$order] : $orders[self::ORDER_COUNT];
272
+ $result = " ORDER BY ${result} ";
273
+ return $result;
274
+ }
275
+
276
+ protected function GetDetailOrderBy($order = '')
277
+ {
278
+ static $orders = array(
279
+ self::ORDER_DATE => 'download_date DESC',
280
+ self::ORDER_IP => 'ip, download_date DESC',
281
+ self::ORDER_REFERER => 'referer, download_date DESC',
282
+ self::ORDER_USER => 'username, download_date DESC',
283
+ );
284
+ $result = isset($orders[$order]) ? $orders[$order] : $orders[self::ORDER_DATE];
285
+ $result = " ORDER BY ${result} ";
286
+ return $result;
287
+ }
288
+
289
+ const FLAGS_NOTEXISTING = 1;
290
+
291
+ protected function GetWhere($flags = 0)
292
+ {
293
+ $conditions = array();
294
+ if ($flags & self::FLAGS_NOTEXISTING)
295
+ $conditions[] = '(file_exists=0)';
296
+ else
297
+ $conditions[] = '(file_exists<>0)';
298
+ if ($conditions)
299
+ $result = ' WHERE ' . implode(' AND ', $conditions);
300
+ else
301
+ $result = '';
302
+ return $result;
303
+ }
304
+
305
+ protected function GetDetailWhere($flags = 0)
306
+ {
307
+ $conditions = array();
308
+ if ($conditions)
309
+ $result = ' AND ' . implode(' AND ', $conditions);
310
+ else
311
+ $result = '';
312
+ return $result;
313
+ }
314
+
315
+ protected function GetLimit($from = 0)
316
+ {
317
+ $from = intval($from);
318
+ if ($from < 0)
319
+ $from = 0;
320
+ $count = self::RECORDS_PER_PAGE;
321
+ $result = " LIMIT ${from}, ${count} ";
322
+ return $result;
323
+ }
324
+
325
+ protected function GetUrlForList($options = array(), $html = TRUE)
326
+ {
327
+ $amp = $html ? '&amp;' : '&';
328
+ $result = get_option('site_url') . 'tools.php?page=' . basename(__FILE__);
329
+ foreach ($options as $name => $value)
330
+ if ($value)
331
+ $result .= $amp . ($html ? htmlspecialchars($name) : $name) . '=' . ($html ? htmlspecialchars($value) : $value);
332
+ return $result;
333
+
334
+ }
335
+
336
+ protected function Paginator($options, $count)
337
+ {
338
+ $from = intval($options['from']);
339
+ $count = intval($count);
340
+ $pages = array();
341
+ if ($from > 0)
342
+ {
343
+ $pages[] = '<a href="' . $this->GetUrlForList(array_merge($options, array('from'=>0))) . '">' . __("First", 'simple-download-monitor') . '</a>';
344
+ $pages[] = '<a href="' . $this->GetUrlForList(array_merge($options, array('from'=>($from>self::RECORDS_PER_PAGE ? $from-self::RECORDS_PER_PAGE : 0)))) . '">' . __("Previous", 'simple-download-monitor') . '</a>';
345
+ }
346
+
347
+ if (($from + self::RECORDS_PER_PAGE) < $count)
348
+ {
349
+ $pages[] = '<a href="' . $this->GetUrlForList(array_merge($options, array('from'=>$from+self::RECORDS_PER_PAGE))) . '">' . __("Next", 'simple-download-monitor') . '</a>';
350
+ $pages[] = '<a href="' . $this->GetUrlForList(array_merge($options, array('from'=>$count-self::RECORDS_PER_PAGE))) . '">' . __("Last", 'simple-download-monitor') . '</a>';
351
+ }
352
+ $result = $pages ? '<div class="pages-list">' . implode(' ', $pages) . '</div>' : '';
353
+ return $result;
354
+ }
355
+
356
+ protected function DownloadList($options)
357
+ {
358
+ global $wpdb;
359
+ $flags = $options['flags'];
360
+ $from = $options['from'];
361
+ $order = $options['order'];
362
+ $detailed = get_option(self::PREFIX . 'detailed');
363
+ ?>
364
+ <div class="wrap">
365
+ <h2><?php echo __('Simple Download Monitor', 'simple-download-monitor'); ?></h2>
366
+ <h3><?php echo ($options['flags'] & self::FLAGS_NOTEXISTING) ? __('Nonexistent downloads', 'simple-download-monitor') : __('All downloads', 'simple-download-monitor'); ?></h3>
367
+ <p><a href="<?php echo $this->GetUrlForList(array_merge($options, array('from' => 0, 'flags' => $options['flags']^self::FLAGS_NOTEXISTING))); ?>"><?php echo ($options['flags'] & self::FLAGS_NOTEXISTING) ? __('Show all downloads', 'simple-download-monitor') : __('Show nonexistent downloads', 'simple-download-monitor'); ?></a></p>
368
+ <table id="sdmon">
369
+ <colgroup>
370
+ <col class="sdmon-rownum" align="right" width="32" />
371
+ <col class="sdmon-filename" />
372
+ <col class="sdmon-count" align="right" width="64" />
373
+ <col class="sdmon-date" align="center" />
374
+ </colgroup>
375
+ <thead>
376
+ <tr>
377
+ <th>&nbsp;</th>
378
+ <th><a href="<?php echo $this->GetUrlForList(array_merge($options, array('order' => self::ORDER_NAME ))); ?>"><?php echo __("Filename", 'simple-download-monitor'); ?></a></th>
379
+ <th><a href="<?php echo $this->GetUrlForList(array_merge($options, array('order' => self::ORDER_COUNT))); ?>"><?php echo __("Download count", 'simple-download-monitor'); ?></a></th>
380
+ <th><a href="<?php echo $this->GetUrlForList(array_merge($options, array('order' => self::ORDER_DATE ))); ?>"><?php echo __("Last date", 'simple-download-monitor'); ?></a></th>
381
+ </tr>
382
+ </thead>
383
+ <tbody><?php
384
+ $table_downloads = $this->table_downloads();
385
+ $where = $this->GetWhere($flags);
386
+ $orderby = $this->GetOrderBy($order);
387
+ $limit = $this->GetLimit($from);
388
+ $sql = "SELECT id, filename, download_count, last_date, file_exists FROM ${table_downloads} ${where} ${orderby} ${limit}";
389
+ $totalcount = $wpdb->get_var("SELECT COUNT(*) FROM ${table_downloads} ${where}");
390
+ $results = $wpdb->get_results($sql, ARRAY_N);
391
+ $rownum = intval($options['from']);
392
+ foreach ($results as $row) {
393
+ $rownum++;
394
+ list($download, $filename, $count, $date, $exists) = $row;
395
+ ?>
396
+ <tr<?php if (!$exists) echo ' class="not-exist"'; ?>>
397
+ <td><?php echo $rownum; ?>.</td>
398
+ <td><?php if ($detailed): ?><a href="<?php echo $this->GetUrlForList(array('download' => $download)); ?>"><?php endif; echo htmlspecialchars($filename); if ($detailed): ?></a><?php endif; ?></td>
399
+ <td><?php echo $count; ?></td>
400
+ <td><?php echo mysql2date('Y-m-d h:i:s', $date, TRUE); ?></td>
401
+ </tr>
402
+ </tbody><?php
403
+ }
404
+ ?>
405
+ </table>
406
+ <?php echo $this->Paginator($options, $totalcount); ?>
407
+ </div><?php
408
+ }
409
+
410
+ protected function DetailedDownloadList($options)
411
+ {
412
+ global $wpdb;
413
+ $flags = $options['flags'];
414
+ $from = $options['from'];
415
+ $order = $options['order'];
416
+ $download = $options['download'];
417
+ $detailed = $options['detailed'];
418
+ $table_downloads = $this->table_downloads();
419
+ list($id, $filename, $count) = $wpdb->get_row($wpdb->prepare("SELECT id, filename, download_count FROM ${table_downloads} WHERE id=%d", $download), ARRAY_N);
420
+ if (!$id)
421
+ {
422
+ DownloadList($options);
423
+ }
424
+ else
425
+ {
426
+ ?>
427
+ <div class="wrap">
428
+ <h2><?php echo __('Simple Download Monitor', 'simple-download-monitor'); ?></h2>
429
+ <h3><?php printf(__('Detailed data for <strong>%s</strong>:', 'simple-download-monitor'), $filename); ?></h3>
430
+ <p><?php printf(__('Total number of downloads: <strong>%d</strong>.', 'simple-download-monitor'), $count); ?></p>
431
+ <table id="sdmon">
432
+ <colgroup>
433
+ <col class="sdmon-rownum" align="right" width="32" />
434
+ <col class="sdmon-date" align="center" />
435
+ <col class="sdmon-ipaddr" />
436
+ <col class="sdmon-referer" />
437
+ <col class="sdmon-username" />
438
+ </colgroup>
439
+ <thead>
440
+ <tr>
441
+ <th>&nbsp;</th>
442
+ <th><a href="<?php echo $this->GetUrlForList(array_merge($options, array('order' => self::ORDER_DATE ))); ?>"><?php echo __("Date", 'simple-download-monitor'); ?></a></th>
443
+ <th><a href="<?php echo $this->GetUrlForList(array_merge($options, array('order' => self::ORDER_IP ))); ?>"><?php echo __("IP address", 'simple-download-monitor'); ?></a></th>
444
+ <th><a href="<?php echo $this->GetUrlForList(array_merge($options, array('order' => self::ORDER_REFERER))); ?>"><?php echo __("Referer", 'simple-download-monitor'); ?></a></th>
445
+ <th><a href="<?php echo $this->GetUrlForList(array_merge($options, array('order' => self::ORDER_USER ))); ?>"><?php echo __("Username", 'simple-download-monitor'); ?></a></th>
446
+ </tr>
447
+ </thead>
448
+ <tbody><?php
449
+ $table_details = $this->table_details();
450
+ $where = $this->GetDetailWhere($flags);
451
+ $orderby = $this->GetDetailOrderBy($order);
452
+ $limit = $this->GetLimit($from);
453
+ $sql = "SELECT download_date, ip, referer, userid, username FROM ${table_details} WHERE download=%d ${where} ${orderby} ${limit}";
454
+ $totalcount = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM ${table_details} WHERE download=%d ${where}", $download));
455
+ $results = $wpdb->get_results($wpdb->prepare($sql, $download), ARRAY_N);
456
+ $rownum = intval($options['from']);
457
+ foreach ($results as $row) {
458
+ $rownum++;
459
+ list($date, $ip, $referer, $userid, $username) = $row;
460
+ ?>
461
+ <tr>
462
+ <td><?php echo $rownum; ?>.</td>
463
+ <td><?php echo mysql2date('Y-m-d h:i:s', $date, TRUE); ?></td>
464
+ <td><?php echo htmlspecialchars($ip); ?></td>
465
+ <td><?php echo htmlspecialchars($referer); ?></td>
466
+ <td><?php echo htmlspecialchars($username); ?></td>
467
+ </tr>
468
+ </tbody><?php
469
+ }
470
+ }
471
+ ?>
472
+ </table>
473
+ <?php echo $this->Paginator($options, $totalcount); ?>
474
+ <p><a href="<?php echo $this->GetUrlForList(); ?>"><?php echo __('Return to full list.', 'simple-download-monitor'); ?></a></p>
475
+ </div><?php
476
+ }
477
+
478
+ public function ActionHead()
479
+ {
480
+ echo '<link type="text/css" rel="stylesheet" href="' . $this->plugin_url . '/css/sdmon.css" />'."\n";
481
+ }
482
+
483
+ }
484
+ }
485
+
486
+ if (!isset($sdmon))
487
+ $sdmon = new SimpleDownloadMonitor();
488
+
489
+ if (!function_exists('SimpleDownloadMonitor_BuildAdminMenu'))
490
+ {
491
+ function SimpleDownloadMonitor_BuildAdminMenu()
492
+ {
493
+ global $sdmon;
494
+ if (isset($sdmon))
495
+ {
496
+ $options_page = add_options_page(__('Simple Download Monitor options', 'simple-download-monitor'), __('Simple Download Monitor', 'simple-download-monitor'), 'manage_options', basename(__FILE__), array(&$sdmon, 'AdminPanel'));
497
+ $tool_page = add_submenu_page('tools.php', __('Simple Download Monitor', 'simple-download-monitor'), __('Simple Download Monitor', 'simple-download-monitor'), 'read', basename(__FILE__), array(&$sdmon, 'ToolsPanel'));
498
+ add_action('admin_head-'.$tool_page, array(&$sdmon, 'ActionHead'));
499
+ }
500
+ }
501
+ }