phpmix-cvs Mailing List for phpMiX Open Source eXperiments (Page 2)
Status: Pre-Alpha
Brought to you by:
markus_petrux
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
(160) |
May
|
Jun
(117) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
---|
From: <php...@li...> - 2006-06-08 03:51:05
|
Update of /cvsroot/phpmix/drupal/modules/akismet/contrib/controlpanel/36x36 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17198/36x36 Log Message: Directory /cvsroot/phpmix/drupal/modules/akismet/contrib/controlpanel/36x36 added to the repository |
From: <php...@li...> - 2006-06-08 03:50:46
|
Update of /cvsroot/phpmix/drupal/modules/akismet/contrib/controlpanel/48x48 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18996/contrib/controlpanel/48x48 Added Files: admin_akismet.png admin_settings_akismet.png Log Message: Added buttons for the control panel module in contrib directory. Buttons are based on Akismet spam stats page. Sadly, I'm very good with graphs, but this is better than nothing (hopefully). --- NEW FILE: admin_akismet.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: admin_settings_akismet.png --- (This appears to be a binary file; contents omitted.) |
From: <php...@li...> - 2006-06-08 03:50:46
|
Update of /cvsroot/phpmix/drupal/modules/akismet/contrib/controlpanel/36x36 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18996/contrib/controlpanel/36x36 Added Files: admin_akismet.png admin_settings_akismet.png Log Message: Added buttons for the control panel module in contrib directory. Buttons are based on Akismet spam stats page. Sadly, I'm very good with graphs, but this is better than nothing (hopefully). --- NEW FILE: admin_akismet.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: admin_settings_akismet.png --- (This appears to be a binary file; contents omitted.) |
From: <php...@li...> - 2006-06-08 03:50:45
|
Update of /cvsroot/phpmix/drupal/modules/akismet/contrib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16736/contrib Log Message: Directory /cvsroot/phpmix/drupal/modules/akismet/contrib added to the repository |
From: <php...@li...> - 2006-06-08 02:49:36
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3334 Added Files: akismet.gif Log Message: Added akismet button for use in block. --- NEW FILE: akismet.gif --- (This appears to be a binary file; contents omitted.) |
From: <php...@li...> - 2006-06-08 02:49:36
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23538 Modified Files: akismet.module Log Message: Implemented a basic moderation queue (it's just a report). Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** akismet.module 7 Jun 2006 15:34:23 -0000 1.9 --- akismet.module 8 Jun 2006 01:38:31 -0000 1.10 *************** *** 3,13 **** /********************************************************************************\ - WARNING: Module is in development! @TODO: Implement a themable block (or something for spam counter). - @TODO: Think about and implement spam moderation queue. - @TODO: Review the help page. @TODO: Implement an opt-in option for administrators to e-mail them when content is posted (maybe for all posts, or for detected spam or nothing). \********************************************************************************/ --- 3,12 ---- /********************************************************************************\ @TODO: Implement a themable block (or something for spam counter). @TODO: Implement an opt-in option for administrators to e-mail them when content is posted (maybe for all posts, or for detected spam or nothing). + @TODO: Review the help page. + @TODO: Enhance moderation queue with a form to allow multiple operations. \********************************************************************************/ *************** *** 30,33 **** --- 29,33 ---- */ function akismet_help($section) { + $output = ''; switch ($section) { case 'admin/modules#description': *************** *** 36,41 **** case 'admin/help/akismet': case 'admin/settings/akismet': ! $output = '<p>'; ! $output .= t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', --- 36,40 ---- case 'admin/help/akismet': case 'admin/settings/akismet': ! $output = t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', *************** *** 43,46 **** --- 42,46 ---- '%akismet' => 'http://akismet.com' )); + case 'admin/akismet': $output .= t('<p>Akismet has caught <strong>%count spam</strong> for you since <strong>%since</strong>.</p>', array('%count' => variable_get('akismet_counter_spam', 0), '%since' => akismet_get_counting_since())); if ($section == 'admin/settings/akismet') { *************** *** 48,51 **** --- 48,59 ---- } break; + case 'admin/akismet/nodes': + $output = t("Below is the list of nodes awaiting for moderation. Click on the titles to see the content, the author's name to view the author's user information. You may also wish to click on the headers to order the nodes upon your needs."); + $output .= '<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use the submit <em>ham</em> operation rather than simply publishing content that was identified as spam (false positives). This is necessary in order to let Akismet learn from its mistakes. Thank you.', array('%akismet' => 'http://akismet.com')); + break; + case 'admin/akismet/comments': + $output = t("Below is the list of comments awaiting for moderation. Click on the subjects to see the comments, the author's name to view the author's user information. You may also wish to click on the headers to order the comments upon your needs."); + $output .= '<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use the submit <em>ham</em> operation rather than simply publishing content that was identified as spam (false positives). This is necessary in order to let Akismet learn from its mistakes. Thank you.', array('%akismet' => 'http://akismet.com')); + break; case 'admin/help#akismet': $output = t('<p>In order to use the <a href="%akismet">Akismet Service</a>, you need a <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.</p> *************** *** 270,273 **** --- 278,287 ---- '#description' => t('Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. This option allows you to specify how long this information will be kept in the database. <em>Spam</em> older than the age specified here will be automatically removed. Requires crontab.') ); + $form['general']['akismet_records_per_page'] = array( + '#type' => 'select', '#title' => t('Records per page'), + '#default_value' => variable_get('akismet_records_per_page', 50), + '#options' => drupal_map_assoc(array(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200)), + '#description' => t('The maximum number of records per page on moderation queue.') + ); $form['node_options'] = array( *************** *** 420,424 **** function akismet_menu($may_cache) { $items = array(); ! if (!$may_cache) { // Paths may look like 'akismet/content_type/content_id/operation' if (arg(0) == 'akismet' && is_numeric(arg(2))) { --- 434,461 ---- function akismet_menu($may_cache) { $items = array(); ! if ($may_cache) { ! // Changes in content types force the menu to be rebuilt, ! // so it should be safe to cache this menu items here. ! // Users will only see this menu if they actually can ! // moderate, at least, one content type. ! $moderator_types = akismet_get_moderator_types(); ! $moderator_types_count = count($moderator_types); ! if ($moderator_types_count > 0) { ! $items[] = array('path' => 'admin/akismet', 'title' => t('akismet moderation queue'), ! 'callback' => 'akismet_callback_queue', ! 'access' => ($moderator_types_count > 0 ? TRUE : FALSE)); ! $items[] = array('path' => 'admin/akismet/overview', 'title' => t('overview'), ! 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => 0); ! if (!isset($moderator_types['comments']) || $moderator_types_count > 1) { ! $items[] = array('path' => 'admin/akismet/nodes', 'title' => t('nodes'), ! 'type' => MENU_LOCAL_TASK, 'weight' => 1); ! } ! if (isset($moderator_types['comments'])) { ! $items[] = array('path' => 'admin/akismet/comments', 'title' => t('comments'), ! 'type' => MENU_LOCAL_TASK, 'weight' => 2); ! } ! } ! } ! else { // Paths may look like 'akismet/content_type/content_id/operation' if (arg(0) == 'akismet' && is_numeric(arg(2))) { *************** *** 737,740 **** --- 774,879 ---- /** + * Menu callback; Moderation queue. + */ + function akismet_callback_queue($op = '') { + // Compute exactly what the current user is allowed to moderate. + $moderator_types = akismet_get_moderator_types(); + $moderator_types_count = count($moderator_types); + $allowed_comments = (isset($moderator_types['comments']) ? TRUE : FALSE); + $allowed_nodes = $moderator_types; + if ($allowed_comments) { + unset($allowed_nodes['comments']); + } + $allowed_nodes_count = count($allowed_nodes); + + if ($allowed_nodes_count > 0) { + $sql_nodetypes = array(); + foreach ($allowed_nodes as $type => $name) { + $sql_nodetypes[] = "'". $type ."'"; + } + $sql_nodetypes = implode(', ', $sql_nodetypes); + $sql_nodes = "SELECT n.*, s.spam_created FROM {akismet_spam_marks} s INNER JOIN {node} n ON s.content_id = n.nid WHERE s.content_type = 'node' AND (n.type IN (". $sql_nodetypes .") OR n.status = 0)"; + $sql_nodes_cnt = "SELECT COUNT(*) AS cnt FROM {akismet_spam_marks} s INNER JOIN {node} n ON s.content_id = n.nid WHERE s.content_type = 'node' AND (n.type IN (". $sql_nodetypes .") OR n.status = 0)"; + } + if ($allowed_comments) { + $sql_comments = "SELECT c.*, s.spam_created FROM {akismet_spam_marks} s INNER JOIN {comments} c ON s.content_id = c.cid WHERE s.content_type = 'comment' OR c.status = ". COMMENT_NOT_PUBLISHED; + $sql_comments_cnt = "SELECT COUNT(*) AS cnt FROM {akismet_spam_marks} s INNER JOIN {comments} c ON s.content_id = c.cid WHERE s.content_type = 'comment' OR c.status = ". COMMENT_NOT_PUBLISHED; + } + + if (empty($op) || $op == 'overview') { + $items = array(); + if ($allowed_nodes_count > 0) { + $count = db_result(db_query(db_rewrite_sql($sql_nodes_cnt))); + $label = ($count > 0 ? l(t('Nodes'), 'admin/akismet/nodes') : t('Nodes')); + $items[] = '<p><strong>'. $label .': '. $count .'</strong></p>'; + } + if ($allowed_comments) { + $count = db_result(db_query(db_rewrite_sql($sql_comments_cnt))); + $label = ($count > 0 ? l(t('Comments'), 'admin/akismet/comments') : t('Comments')); + $items[] = '<p><strong>'. $label .': '. $count .'</strong></p>'; + } + return '<h3>'. t('Items in moderation queue:') .'</h3>'. theme('item_list', $items); + } + + if ($op == 'nodes') { + $sql = $sql_nodes; + $sql_count = $sql_nodes_cnt; + $headers = array( + array('data' => t('Title'), 'field' => 'title'), + array('data' => t('Type'), 'field' => 'type'), + array('data' => t('Author'), 'field' => 'name'), + array('data' => t('Status'), 'field' => 'status'), + array('data' => t('Created'), 'field' => 'spam_created', 'sort' => 'desc') + ); + } + else { // comments + $sql = $sql_comments; + $sql_count = $sql_comments_cnt; + $headers = array( + array('data' => t('Subject'), 'field' => 'subject'), + array('data' => t('Author'), 'field' => 'name'), + array('data' => t('Status'), 'field' => 'status'), + array('data' => t('Created'), 'field' => 'spam_created', 'sort' => 'desc') + ); + } + + $records_per_page = variable_get('akismet_records_per_page', 50); + $result = pager_query($sql . tablesort_sql($headers), $records_per_page, 0, $sql_cnt); + $rows = array(); + while ($content = db_fetch_object($result)) { + if ($op == 'nodes') { + $rows[] = array( + l($content->title, "node/$content->nid", array('title' => truncate_utf8($content->body, 128))) .' '. theme('mark', node_mark($content->nid, $content->changed)), + node_get_name($content), + theme('username', $content), + ($node->status ? t('published') : t('not published')), + t('%time ago', array('%time' => format_interval(time() - $content->spam_created))) + ); + } + else { // comments + $content->name = $content->uid ? $content->registered_name : $content->name; + $rows[] = array( + l($content->subject, "node/$content->nid", array('title' => truncate_utf8($content->comment, 128)), NULL, "comment-$content->cid") .' '. theme('mark', node_mark($content->nid, $content->timestamp)), + theme('username', $content), + ($content->status == COMMENT_PUBLISHED ? t('published') : t('not published')), + t('%time ago', array('%time' => format_interval(time() - $content->spam_created))) + ); + } + } + + if (count($rows) <= 0) { + if ($op == 'nodes') { + drupal_set_message(t('There are no nodes in the moderation queue.')); + } + else { // comments + drupal_set_message(t('There are no comments in the moderation queue.')); + } + return ''; + } + + return theme('table', $headers, $rows) . theme('pager', NULL, $records_per_page, 0); + } + + /** * Check if specified content is marked as spam. * *************** *** 771,803 **** /** ! * Is current user spam moderator? * ! * @param string Moderator Type ('comments' or node type). ! * @return boolean TRUE if current user is moderator of specified type; FALSE otherwise. */ ! function akismet_is_spam_moderator($moderator_type) { ! static $cached_permissions = array(); ! static $cached_node_types = FALSE; ! if (!isset($cached_permissions[$moderator_type])) { ! if ($moderator_type == 'comments') { ! $cached_permissions[$moderator_type] = user_access('administer comments') || user_access('moderate spam in comments'); ! } ! else if (user_access('administer nodes')) { ! $cached_permissions[$moderator_type] = TRUE; } else { ! if (!$cached_node_types) { ! $cached_node_types = node_get_types(); ! } ! if (!isset($cached_node_types[$moderator_type])) { ! $cached_permissions[$moderator_type] = FALSE; ! } ! else { ! $cached_permissions[$moderator_type] = user_access('moderate spam in nodes of type '. $cached_node_types[$moderator_type]); } } } ! return $cached_permissions[$moderator_type]; } --- 910,954 ---- /** ! * Get the types the current user is allowed to moderate. * ! * @return array Moderator Types. */ ! function akismet_get_moderator_types() { ! static $moderator_types = FALSE; ! if ($moderator_types === FALSE) { ! $moderator_types = array(); ! $node_types = node_get_types(); ! ! if (user_access('administer nodes')) { ! foreach ($node_types as $type => $name) { ! $moderator_types[$type] = $name; ! } } else { ! foreach ($node_types as $type => $name) { ! if (user_access('moderate spam in nodes of type '. $node_types[$type])) { ! $moderator_types[$type] = $name; ! } } } + + if (user_access('administer comments') || user_access('moderate spam in comments')) { + $moderator_types['comments'] = t('comments'); + } } ! ! return $moderator_types; ! } ! ! /** ! * Is current user spam moderator? ! * ! * @param string Moderator Type ('comments' or node type). ! * @return boolean TRUE if current user is moderator of specified type; FALSE otherwise. ! */ ! function akismet_is_spam_moderator($moderator_type) { ! $moderator_types = akismet_get_moderator_types(); ! return isset($moderator_types[$moderator_type]); } |
From: <php...@li...> - 2006-06-07 18:06:25
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19070 Modified Files: akismet.module Log Message: Fixed queries in hook_cron to detect orphans. Also, added list of affected content IDs to the message logged to watchdog. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** akismet.module 7 Jun 2006 14:06:08 -0000 1.8 --- akismet.module 7 Jun 2006 15:34:23 -0000 1.9 *************** *** 110,114 **** // This is why this cron task is being more complex that it could really be. Anyway, these // queries shouldn't be too heavy. ! $result = db_query("SELECT s.content_id FROM {akismet_spam_marks} s LEFT JOIN {node} n ON s.content_type = 'node' AND s.content_id = n.nid WHERE n.nid IS NULL"); if (db_num_rows($result)) { while ($s = db_fetch_object($result)) { --- 110,114 ---- // This is why this cron task is being more complex that it could really be. Anyway, these // queries shouldn't be too heavy. ! $result = db_query("SELECT s.content_id FROM {akismet_spam_marks} s LEFT JOIN {node} n ON s.content_id = n.nid WHERE s.content_type = 'node' AND n.nid IS NULL"); if (db_num_rows($result)) { while ($s = db_fetch_object($result)) { *************** *** 118,122 **** } } ! $result = db_query("SELECT s.content_id FROM {akismet_spam_marks} s LEFT JOIN {comments} c ON s.content_type = 'comment' AND s.content_id = c.cid WHERE c.cid IS NULL"); if (db_num_rows($result)) { while ($s = db_fetch_object($result)) { --- 118,122 ---- } } ! $result = db_query("SELECT s.content_id FROM {akismet_spam_marks} s LEFT JOIN {comments} c ON s.content_id = c.cid WHERE s.content_type = 'comment' AND c.cid IS NULL"); if (db_num_rows($result)) { while ($s = db_fetch_object($result)) { *************** *** 135,150 **** $expired_cids_removed = count($expired_content_spam['cids']); if ($expired_nids_removed > 0) { foreach ($expired_content_spam['nids'] as $nid) { ! akismet_content_delete('node', $nid); } - watchdog('cron', t('Akismet housekeeping') .': '. format_plural($expired_nids_removed, '1 expired spam node removed from database', '%count expired spam nodes removed from database')); - $clear_cache = TRUE; } if ($expired_cids_removed > 0) { foreach ($expired_content_spam['cids'] as $cid) { ! akismet_content_delete('comment', $cid); } - watchdog('cron', t('Akismet housekeeping') .': '. format_plural($expired_cids_removed, '1 expired spam comment removed from database', '%count expired spam comments removed from database')); - $clear_cache = TRUE; } --- 135,168 ---- $expired_cids_removed = count($expired_content_spam['cids']); if ($expired_nids_removed > 0) { + $deleted_items = array(); + $delete_count = 0; foreach ($expired_content_spam['nids'] as $nid) { ! if (akismet_content_delete('node', $nid)) { ! $deleted_items[] = $nid; ! $delete_count++; ! } ! } ! if ($delete_count > 0) { ! $message = t('Akismet housekeeping') .': '. format_plural($delete_count, '1 expired spam node removed from database', '%count expired spam nodes removed from database'). ! '<br />'.t('Node ID List: %nids', array('%nids' => implode(',', $deleted_items))); ! watchdog('cron', $message); ! $clear_cache = TRUE; } } if ($expired_cids_removed > 0) { + $deleted_items = array(); + $delete_count = 0; foreach ($expired_content_spam['cids'] as $cid) { ! if (akismet_content_delete('comment', $cid)) { ! $deleted_items[] = $cid; ! $delete_count++; ! } ! } ! if ($delete_count > 0) { ! $message = t('Akismet housekeeping') .': '. format_plural($delete_count, '1 expired spam comment removed from database', '%count expired spam comments removed from database'). ! '<br />'.t('Comment ID List: %cids', array('%cids' => implode(',', $deleted_items))); ! watchdog('cron', $message); ! $clear_cache = TRUE; } } *************** *** 154,164 **** $spam_marks_removed = $spam_nids_removed + $spam_cids_removed; if ($spam_nids_removed > 0) { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'node' AND content_id IN (%s)", implode(',', $obsolete_spam_marks['nids'])); } if ($spam_cids_removed > 0) { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'comment' AND content_id IN (%s)", implode(',', $obsolete_spam_marks['cids'])); } if ($spam_marks_removed > 0) { ! watchdog('cron', t('Akismet housekeeping') .': '. format_plural($spam_marks_removed, '1 spam mark removed from database', '%count spam marks removed from database')); $clear_cache = TRUE; } --- 172,191 ---- $spam_marks_removed = $spam_nids_removed + $spam_cids_removed; if ($spam_nids_removed > 0) { ! $spam_nids_list = implode(',', $obsolete_spam_marks['nids']); ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'node' AND content_id IN (%s)", $spam_nids_list); } if ($spam_cids_removed > 0) { ! $spam_cids_list = implode(',', $obsolete_spam_marks['cids']); ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'comment' AND content_id IN (%s)", $spam_cids_list); } if ($spam_marks_removed > 0) { ! $message = t('Akismet housekeeping') .': '. format_plural($spam_marks_removed, '1 spam mark removed from database', '%count spam marks removed from database'); ! if (isset($spam_nids_list)) { ! $message .= '<br />'. t('Node ID List: %nids', array('%nids' => $spam_nids_list)); ! } ! if (isset($spam_cids_list)) { ! $message .= '<br />'. t('Comment ID List: %cids', array('%cids' => $spam_cids_list)); ! } ! watchdog('cron', $message); $clear_cache = TRUE; } *************** *** 809,812 **** --- 836,840 ---- * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. + * @return boolean TRUE if specified was there; FALSE otherwise. */ function akismet_content_delete($content_type, $content_id) { *************** *** 835,838 **** --- 863,867 ---- // Record the event to watchdog. watchdog('content', t('%type: deleted %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title)))); + return TRUE; } } *************** *** 842,847 **** --- 871,878 ---- _comment_delete_thread($comment); _comment_update_node_statistics($comment->cid); + return TRUE; } } + return FALSE; } |
From: <php...@li...> - 2006-06-07 18:06:18
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8767 Modified Files: akismet.module Log Message: Implemented separate permissions for moderating spam in comments and/or each node type installed on the system. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** akismet.module 7 Jun 2006 12:33:44 -0000 1.7 --- akismet.module 7 Jun 2006 14:06:08 -0000 1.8 *************** *** 72,76 **** */ function akismet_perm() { ! return array('post with no akismet checking'); } --- 72,84 ---- */ function akismet_perm() { ! $perms = array(); ! ! foreach (node_get_types() as $type => $name) { ! $perms[] = 'moderate spam in nodes of type '. $name; ! } ! $perms[] = 'moderate spam in comments'; ! $perms[] = 'post with no akismet checking'; ! ! return $perms; } *************** *** 240,253 **** '#collapsible' => TRUE, '#collapsed' => TRUE ); - $types = node_get_types(); $form['node_options']['akismet_check_nodetypes'] = array( '#type' => 'checkboxes', '#title' => t('Check for spam in these node types'), ! '#options' => $types, '#default_value' => variable_get('akismet_check_nodetypes', NULL), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> spam check for nodes of types specified here. When this option is enabled, a request will be sent to the <a href="%akismet">Akismet Service</a>, in real time. If the <a href="%akismet">Akismet Service</a> was down, nodes would simply be queued for manual moderation. Users with <em>%admin-nodes</em> permission are exempt from this check.', array( '%akismet' => 'http://akismet.com', ! '%admin-nodes' => t('administer nodes') )) ); --- 248,261 ---- '#collapsible' => TRUE, '#collapsed' => TRUE ); $form['node_options']['akismet_check_nodetypes'] = array( '#type' => 'checkboxes', '#title' => t('Check for spam in these node types'), ! '#options' => node_get_types(), '#default_value' => variable_get('akismet_check_nodetypes', NULL), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> spam check for nodes of types specified here. When this option is enabled, a request will be sent to the <a href="%akismet">Akismet Service</a>, in real time. If the <a href="%akismet">Akismet Service</a> was down, nodes would simply be queued for manual moderation. Users with <a href="%admin-access">%admin-nodes</a> permission and <a href="%admin-access">spam moderators</a> are exempt from this check.', array( '%akismet' => 'http://akismet.com', ! '%admin-nodes' => t('administer nodes'), ! '%admin-access' => url('admin/access') )) ); *************** *** 257,263 **** '#options' => $enable_options, '#default_value' => variable_get('akismet_node_publish_links', 0), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>publish</em>/<em>unpublish</em> operations in nodes. If enabled, these links will only be displayed to users with <em>%admin-nodes</em> permission.', array( ! '%admin-nodes' => t('administer nodes') )) ); --- 265,272 ---- '#options' => $enable_options, '#default_value' => variable_get('akismet_node_publish_links', 0), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>publish</em>/<em>unpublish</em> operations in nodes. If enabled, these links will only be displayed to <a href="%admin-access">spam moderators</a> and users with <a href="%admin-access">%admin-nodes</a> permission.', array( ! '%admin-nodes' => t('administer nodes'), ! '%admin-access' => url('admin/access') )) ); *************** *** 267,273 **** '#options' => $enable_options, '#default_value' => variable_get('akismet_node_spam_links', 0), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>submit spam</em>/<em>ham</em> operations in nodes. If enabled, these links will only be displayed to users with <em>%admin-nodes</em> permission.', array( ! '%admin-nodes' => t('administer nodes') )) .'<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use these links to submit missed spam and false positives (ham), otherwise Akismet will never learn from its mistakes. Thank you.', --- 276,283 ---- '#options' => $enable_options, '#default_value' => variable_get('akismet_node_spam_links', 0), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>submit spam</em>/<em>ham</em> operations in nodes. If enabled, these links will only be displayed to <a href="%admin-access">spam moderators</a> and users with <a href="%admin-access">%admin-nodes</a> permission.', array( ! '%admin-nodes' => t('administer nodes'), ! '%admin-access' => url('admin/access') )) .'<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use these links to submit missed spam and false positives (ham), otherwise Akismet will never learn from its mistakes. Thank you.', *************** *** 287,294 **** '#options' => $enable_options, '#default_value' => variable_get('akismet_check_comments', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> spam check for comments. When this option is enabled, a request will be sent to the <a href="%akismet">Akismet Service</a>, in real time. If the <a href="%akismet">Akismet Service</a> was down, comments would simply be queued for manual moderation. Users with <em>%admin-comments</em> permission are exempt from this check.', array( '%akismet' => 'http://akismet.com', ! '%admin-comments' => t('administer comments') )) ); --- 297,305 ---- '#options' => $enable_options, '#default_value' => variable_get('akismet_check_comments', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> spam check for comments. When this option is enabled, a request will be sent to the <a href="%akismet">Akismet Service</a>, in real time. If the <a href="%akismet">Akismet Service</a> was down, comments would simply be queued for manual moderation. Users with <a href="%admin-access">%admin-comments</a> permission and <a href="%admin-access">spam moderators</a> are exempt from this check.', array( '%akismet' => 'http://akismet.com', ! '%admin-comments' => t('administer comments'), ! '%admin-access' => url('admin/access') )) ); *************** *** 298,304 **** '#options' => $enable_options, '#default_value' => variable_get('akismet_comment_publish_links', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>publish</em>/<em>unpublish</em> operations in comments. If enabled, these links will only be displayed to users with <em>%admin-comments</em> permission.', array( ! '%admin-comments' => t('administer comments') )) ); --- 309,316 ---- '#options' => $enable_options, '#default_value' => variable_get('akismet_comment_publish_links', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>publish</em>/<em>unpublish</em> operations in comments. If enabled, these links will only be displayed to <a href="%admin-access">spam moderators</a> and users with <a href="%admin-access">%admin-comments</a> permission.', array( ! '%admin-comments' => t('administer comments'), ! '%admin-access' => url('admin/access') )) ); *************** *** 308,314 **** '#options' => $enable_options, '#default_value' => variable_get('akismet_comment_spam_links', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>submit spam</em>/<em>ham</em> operations in comments. If enabled, these links will only be displayed to users with <em>%admin-comments</em> permission.', array( ! '%admin-comments' => t('administer comments') )) .'<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use these links to submit missed spam and false positives (ham), otherwise Akismet will never learn from its mistakes. Thank you.', --- 320,327 ---- '#options' => $enable_options, '#default_value' => variable_get('akismet_comment_spam_links', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>submit spam</em>/<em>ham</em> operations in comments. If enabled, these links will only be displayed to <a href="%admin-access">spam moderators</a> and users with <a href="%admin-access">%admin-comments</a> permission.', array( ! '%admin-comments' => t('administer comments'), ! '%admin-access' => url('admin/access') )) .'<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use these links to submit missed spam and false positives (ham), otherwise Akismet will never learn from its mistakes. Thank you.', *************** *** 392,400 **** $callback = 'akismet_callback_set_spam_status'; } ! if (isset($callback) && akismet_content_exists($content_type, arg(2))) { ! $items[] = array('path' => 'akismet', 'title' => t('switch content status'), ! 'callback' => $callback, ! 'access' => ($content_type == 'node' ? user_access('administer nodes') : user_access('administer comments')), ! 'type' => MENU_CALLBACK); } } --- 405,416 ---- $callback = 'akismet_callback_set_spam_status'; } ! if (isset($callback)) { ! $moderator_type = akismet_content_get_moderator_type($content_type, arg(2)); ! if (!empty($moderator_type)) { ! $items[] = array('path' => 'akismet', 'title' => t('switch content status'), ! 'callback' => $callback, ! 'access' => akismet_is_spam_moderator($moderator_type), ! 'type' => MENU_CALLBACK); ! } } } *************** *** 409,413 **** function akismet_link($type, $content = 0, $main = 0) { $links = array(); ! if ($type == 'node' && user_access('administer nodes')) { if (variable_get('akismet_node_publish_links', 0)) { if ($content->status) { --- 425,429 ---- function akismet_link($type, $content = 0, $main = 0) { $links = array(); ! if ($type == 'node' && akismet_is_spam_moderator($content->type)) { if (variable_get('akismet_node_publish_links', 0)) { if ($content->status) { *************** *** 427,431 **** } } ! else if ($type == 'comment' && user_access('administer comments')) { if (variable_get('akismet_comment_publish_links', 1)) { if ($content->status == COMMENT_PUBLISHED) { --- 443,447 ---- } } ! else if ($type == 'comment' && akismet_is_spam_moderator('comments')) { if (variable_get('akismet_comment_publish_links', 1)) { if ($content->status == COMMENT_PUBLISHED) { *************** *** 542,546 **** // Also quit asap, if current user has administration permission. ! if (user_access('administer nodes')) { break; } --- 558,562 ---- // Also quit asap, if current user has administration permission. ! if (akismet_is_spam_moderator($node->type)) { break; } *************** *** 606,610 **** // Hook into comment edit/reply form. if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1)) { ! if (!user_access('administer comments')) { if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { // This is the simple hook method, we already have the $cid. --- 622,626 ---- // Hook into comment edit/reply form. if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1)) { ! if (!akismet_is_spam_moderator('comments')) { if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { // This is the simple hook method, we already have the $cid. *************** *** 698,702 **** * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. ! * @return boolean TRUE if spam, FALSE otherwise. */ function akismet_content_is_spam($content_type, $content_id) { --- 714,718 ---- * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. ! * @return boolean TRUE if content is marked as spam; FALSE otherwise. */ function akismet_content_is_spam($content_type, $content_id) { *************** *** 705,722 **** /** ! * Check if specified content exists. * * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. ! * @return boolean TRUE if content exists; FALSE otherwise. */ ! function akismet_content_exists($content_type, $content_id) { if ($content_type == 'node') { ! return db_result(db_query('SELECT 1 FROM {node} WHERE nid = %d', $content_id)); } ! if ($content_type == 'comment') { ! return db_result(db_query('SELECT 1 FROM {comments} WHERE cid = %d', $content_id)); } ! return FALSE; } --- 721,776 ---- /** ! * Get moderator type required for specified content. * * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. ! * @return string Moderator Type or empty string if content is not found. */ ! function akismet_content_get_moderator_type($content_type, $content_id) { if ($content_type == 'node') { ! $moderator_type = db_result(db_query('SELECT type FROM {node} WHERE nid = %d', $content_id)); ! if (!$moderator_type) { ! $moderator_type = ''; ! } } ! else if ($content_type == 'comment') { ! $moderator_type = (db_result(db_query('SELECT 1 FROM {comments} WHERE cid = %d', $content_id)) ? 'comments' : ''); } ! else { ! $moderator_type = ''; ! } ! return $moderator_type; ! } ! ! /** ! * Is current user spam moderator? ! * ! * @param string Moderator Type ('comments' or node type). ! * @return boolean TRUE if current user is moderator of specified type; FALSE otherwise. ! */ ! function akismet_is_spam_moderator($moderator_type) { ! static $cached_permissions = array(); ! static $cached_node_types = FALSE; ! ! if (!isset($cached_permissions[$moderator_type])) { ! if ($moderator_type == 'comments') { ! $cached_permissions[$moderator_type] = user_access('administer comments') || user_access('moderate spam in comments'); ! } ! else if (user_access('administer nodes')) { ! $cached_permissions[$moderator_type] = TRUE; ! } ! else { ! if (!$cached_node_types) { ! $cached_node_types = node_get_types(); ! } ! if (!isset($cached_node_types[$moderator_type])) { ! $cached_permissions[$moderator_type] = FALSE; ! } ! else { ! $cached_permissions[$moderator_type] = user_access('moderate spam in nodes of type '. $cached_node_types[$moderator_type]); ! } ! } ! } ! return $cached_permissions[$moderator_type]; } |
From: <php...@li...> - 2006-06-07 12:34:25
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23478 Modified Files: akismet.module Log Message: Previous implementation of hook_cron was not really complete. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** akismet.module 6 Jun 2006 00:08:35 -0000 1.6 --- akismet.module 7 Jun 2006 12:33:44 -0000 1.7 *************** *** 35,39 **** break; case 'admin/help/akismet': ! $output = t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', --- 35,41 ---- break; case 'admin/help/akismet': ! case 'admin/settings/akismet': ! $output = '<p>'; ! $output .= t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', *************** *** 41,49 **** '%akismet' => 'http://akismet.com' )); break; case 'admin/help#akismet': $output = t('<p>In order to use the <a href="%akismet">Akismet Service</a>, you need a <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.</p> <p>The <em>akismet module</em> may automatically check for spam posted in content (nodes and/or comments) by any user, except node or comment administrators respectively. It is also possible, from the <a href="%access-control">access control</a> panel, to grant <em>%no-check-perm</em> permission to <em>user roles</em> of your choice.</p> ! <p>Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. There is <a href="%akismet-settings">an option</a> that allows you to specify how long this information will be kept in the database. <em>Spam</em> older than a specified interval will be automatically removed. Requires crontab.</p> <p>Automatic spam detection can be enabled or disabled by content type and/or comments. In addition to this, the <em>akismet module</em> makes it easy for <em>content administrators</em> to manually <em>publish</em>/<em>unpublish</em> content and <em>mark</em>/<em>unmark</em> content as spam, from links available at the bottom of content.</p> <p></p>', --- 43,55 ---- '%akismet' => 'http://akismet.com' )); + $output .= t('<p>Akismet has caught <strong>%count spam</strong> for you since <strong>%since</strong>.</p>', array('%count' => variable_get('akismet_counter_spam', 0), '%since' => akismet_get_counting_since())); + if ($section == 'admin/settings/akismet') { + $output .= theme('more_help_link', url('admin/help/akismet')); + } break; case 'admin/help#akismet': $output = t('<p>In order to use the <a href="%akismet">Akismet Service</a>, you need a <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.</p> <p>The <em>akismet module</em> may automatically check for spam posted in content (nodes and/or comments) by any user, except node or comment administrators respectively. It is also possible, from the <a href="%access-control">access control</a> panel, to grant <em>%no-check-perm</em> permission to <em>user roles</em> of your choice.</p> ! <p>Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. There is <a href="%akismet-settings">an option</a> that allows you to specify how long this information will be kept in the database. <em>Spam</em> older than a specified age will be automatically removed. Requires crontab.</p> <p>Automatic spam detection can be enabled or disabled by content type and/or comments. In addition to this, the <em>akismet module</em> makes it easy for <em>content administrators</em> to manually <em>publish</em>/<em>unpublish</em> content and <em>mark</em>/<em>unmark</em> content as spam, from links available at the bottom of content.</p> <p></p>', *************** *** 58,71 **** )); break; - case 'admin/settings/akismet': - $output = t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p> - <p>This panel allows you to configure all <em>akismet module</em> options. For further information, please consult the <a href="%help-page">help page</a> of the module.</p>', - array( - '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', - '%drupal' => 'http://drupal.org', - '%akismet' => 'http://akismet.com', - '%help-page' => url('admin/help/akismet') - )); - break; } return $output; --- 64,67 ---- *************** *** 83,88 **** */ function akismet_cron() { ! // Remove spam older than... ! db_query('DELETE FROM {akismet_spam_marks} WHERE spam_created < %d', time() - variable_get('akismet_remove_spam_interval', 259200)); } --- 79,163 ---- */ function akismet_cron() { ! // Expired content spam that we have to remove from each content repository. ! $expired_content_spam = array('nids'=>array(), 'cids'=>array()); ! // Spam marks that we have to remove from the 'spam marks' table. ! $obsolete_spam_marks = array('nids'=>array(), 'cids'=>array()); ! ! // Retrieve the list of expired content spam, based on the age specified in the settings panel. ! $expire_spam_age = variable_get('akismet_remove_spam_age', 259200); ! if ($expire_spam_age > 0) { ! $result = db_query('SELECT content_type, content_id FROM {akismet_spam_marks} WHERE spam_created < %d', time() - $expire_spam_age); ! if (db_num_rows($result)) { ! while ($s = db_fetch_object($result)) { ! $key = ($s->content_type == 'node' ? 'nids' : 'cids'); ! $expired_content_spam[$key][] = $s->content_id; ! $obsolete_spam_marks[$key][] = $s->content_id; ! } ! } ! } ! ! // Deal with possible spam marks for content that have already been removed from database. ! // Note: when Drupal deletes a node, all its comments are deleted, but no hook is invoked, ! // so that may lead to orphans in the 'spam marks' table. ! // This is why this cron task is being more complex that it could really be. Anyway, these ! // queries shouldn't be too heavy. ! $result = db_query("SELECT s.content_id FROM {akismet_spam_marks} s LEFT JOIN {node} n ON s.content_type = 'node' AND s.content_id = n.nid WHERE n.nid IS NULL"); ! if (db_num_rows($result)) { ! while ($s = db_fetch_object($result)) { ! if (!in_array($s->content_id, $obsolete_spam_marks['nids'])) { ! $obsolete_spam_marks['nids'][] = $s->content_id; ! } ! } ! } ! $result = db_query("SELECT s.content_id FROM {akismet_spam_marks} s LEFT JOIN {comments} c ON s.content_type = 'comment' AND s.content_id = c.cid WHERE c.cid IS NULL"); ! if (db_num_rows($result)) { ! while ($s = db_fetch_object($result)) { ! if (!in_array($s->content_id, $obsolete_spam_marks['cids'])) { ! $obsolete_spam_marks['cids'][] = $s->content_id; ! } ! } ! } ! ! // From this point on is where we really will delete stuff from database. ! // Drupal cache will need to be cleared so anonymous users get updated views. ! $clear_cache = FALSE; ! ! // Remove expired spam from each content repository. ! $expired_nids_removed = count($expired_content_spam['nids']); ! $expired_cids_removed = count($expired_content_spam['cids']); ! if ($expired_nids_removed > 0) { ! foreach ($expired_content_spam['nids'] as $nid) { ! akismet_content_delete('node', $nid); ! } ! watchdog('cron', t('Akismet housekeeping') .': '. format_plural($expired_nids_removed, '1 expired spam node removed from database', '%count expired spam nodes removed from database')); ! $clear_cache = TRUE; ! } ! if ($expired_cids_removed > 0) { ! foreach ($expired_content_spam['cids'] as $cid) { ! akismet_content_delete('comment', $cid); ! } ! watchdog('cron', t('Akismet housekeeping') .': '. format_plural($expired_cids_removed, '1 expired spam comment removed from database', '%count expired spam comments removed from database')); ! $clear_cache = TRUE; ! } ! ! // Remove obsolete spam marks from database. ! $spam_nids_removed = count($obsolete_spam_marks['nids']); ! $spam_cids_removed = count($obsolete_spam_marks['cids']); ! $spam_marks_removed = $spam_nids_removed + $spam_cids_removed; ! if ($spam_nids_removed > 0) { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'node' AND content_id IN (%s)", implode(',', $obsolete_spam_marks['nids'])); ! } ! if ($spam_cids_removed > 0) { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'comment' AND content_id IN (%s)", implode(',', $obsolete_spam_marks['cids'])); ! } ! if ($spam_marks_removed > 0) { ! watchdog('cron', t('Akismet housekeeping') .': '. format_plural($spam_marks_removed, '1 spam mark removed from database', '%count spam marks removed from database')); ! $clear_cache = TRUE; ! } ! ! // If anything was removed, then clear Drupal cache. ! if ($clear_cache) { ! akismet_clear_cache(); ! } } *************** *** 146,156 **** '#description' => t('This option allows you to specify the connection timeout in seconds that is used for real time Akismet connections.') ); ! $interval_options = drupal_map_assoc(array(0, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval'); ! $interval_options[0] = t('never'); ! $form['general']['akismet_remove_spam_interval'] = array( '#type' => 'select', '#title' => t('Remove spam older than'), ! '#default_value' => variable_get('akismet_remove_spam_interval', 259200), ! '#options' => $interval_options, ! '#description' => t('Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. This option allows you to specify how long this information will be kept in the database. <em>Spam</em> older than the interval specified here will be automatically removed. Requires crontab.') ); --- 221,237 ---- '#description' => t('This option allows you to specify the connection timeout in seconds that is used for real time Akismet connections.') ); ! $age_options = drupal_map_assoc(array(0, 3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 1814400), 'format_interval'); ! $age_options[0] = t('never'); ! $age_options[2592000] = t('1 month'); ! $age_options[5184000] = t('2 months'); ! $age_options[7776000] = t('3 months'); ! $age_options[10368000] = t('4 months'); ! $age_options[15768000] = t('6 months'); ! $age_options[31536000] = t('1 year'); ! $form['general']['akismet_remove_spam_age'] = array( '#type' => 'select', '#title' => t('Remove spam older than'), ! '#default_value' => variable_get('akismet_remove_spam_age', 259200), ! '#options' => $age_options, ! '#description' => t('Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. This option allows you to specify how long this information will be kept in the database. <em>Spam</em> older than the age specified here will be automatically removed. Requires crontab.') ); *************** *** 276,279 **** --- 357,379 ---- /** + * Format the 'Counting since' date. + * + * @return string Counting since date formatted according to module settings. + */ + function akismet_get_counting_since() { + $since = variable_get('akismet_counter_since', array('day' => date('j'), 'month' => date('n'), 'year' => date('Y'))); + $format = variable_get('akismet_counter_date_format', 'F j, Y'); + $replace = array( + 'd' => sprintf('%02d', $since['day']), + 'j' => $since['day'], + 'm' => sprintf('%02d', $since['month']), + 'M' => format_date(gmmktime(0, 0, 0, $since['month'], 2, 1970), 'custom', 'M', 0), + 'F' => format_date(gmmktime(0, 0, 0, $since['month'], 2, 1970), 'custom', 'F', 0), + 'Y' => $since['year'] + ); + return strtr($format, $replace); + } + + /** * Implementation of hook_menu(). */ *************** *** 471,475 **** drupal_set_message(t('Your %content-type-name has been queued for moderation by site administrators and will be published after approval.', array('%content-type-name' => $content_type_name))); ! // Add an entry to the watchdog log. if ($akismet_api_result == AKISMET_API_RESULT_ERROR) { watchdog('content', t('Akismet service seems to be down, %content-type-name queued for manual approval: %title', array('%content-type-name' => $content_type_name, '%title' => theme('placeholder', $node->title))), WATCHDOG_WARNING, l(t('view'), "node/$node->nid")); --- 571,575 ---- drupal_set_message(t('Your %content-type-name has been queued for moderation by site administrators and will be published after approval.', array('%content-type-name' => $content_type_name))); ! // Record the event to watchdog. if ($akismet_api_result == AKISMET_API_RESULT_ERROR) { watchdog('content', t('Akismet service seems to be down, %content-type-name queued for manual approval: %title', array('%content-type-name' => $content_type_name, '%title' => theme('placeholder', $node->title))), WATCHDOG_WARNING, l(t('view'), "node/$node->nid")); *************** *** 578,582 **** drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.')); ! // Add an entry to the watchdog log. if ($akismet_api_result == AKISMET_API_RESULT_ERROR) { watchdog('content', t('Akismet service seems to be down, comment queued for manual approval: %subject', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); --- 678,682 ---- drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.')); ! // Record the event to watchdog. if ($akismet_api_result == AKISMET_API_RESULT_ERROR) { watchdog('content', t('Akismet service seems to be down, comment queued for manual approval: %subject', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); *************** *** 637,641 **** else if ($content_type == 'comment') { $content = db_fetch_object(db_query(db_rewrite_sql('SELECT c.*, u.name AS registered_name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', 'c'), $content_id)); ! if ($content->uid) { $content->name = $content->registered_name; } --- 737,744 ---- else if ($content_type == 'comment') { $content = db_fetch_object(db_query(db_rewrite_sql('SELECT c.*, u.name AS registered_name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', 'c'), $content_id)); ! if (empty($content->cid)) { ! $content = FALSE; ! } ! else if ($content->uid) { $content->name = $content->registered_name; } *************** *** 648,651 **** --- 751,810 ---- /** + * Delete a node or a comment. + * + * @param string Content type; can be either 'node' or 'comment'. + * @param integer Content ID; can be either a nid or a cid. + */ + function akismet_content_delete($content_type, $content_id) { + if ($content_type == 'node') { + $node = akismet_content_load($content_type, $content_id); + if ($node) { + // Sadly, we cannot invoke node_delete() because it checks for the + // user to have delete permission on nodes, and this function may + // be invoked from a cron task, which is run as anonymous user, so + // we have to hardcode the low level parts here. + + // Code based on node.module::node_delete(). + + db_query('DELETE FROM {node} WHERE nid = %d', $node->nid); + db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid); + + // Call the node-specific callback (if any): + node_invoke($node, 'delete'); + node_invoke_nodeapi($node, 'delete'); + + // Remove this node from the search index if needed. + if (function_exists('search_wipe')) { + search_wipe($node->nid, 'node'); + } + + // Record the event to watchdog. + watchdog('content', t('%type: deleted %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title)))); + } + } + else if ($content_type == 'comment') { + $comment = akismet_content_load($content_type, $content_id); + if ($comment) { + _comment_delete_thread($comment); + _comment_update_node_statistics($comment->cid); + } + } + } + + /** + * Clear Drupal cache. + * + * This function needs to be called so anonymous users get updated content + * when certain operations have been executed. + */ + function akismet_clear_cache() { + static $already_done = FALSE; + if (!$already_done) { + cache_clear_all(); + $already_done = TRUE; + } + } + + /** * Mark content as spam or remove the mark. * *************** *** 693,696 **** --- 852,856 ---- watchdog('content', t('%action: %title', array('%action' => $action, '%title' => theme('placeholder', $content_title))), WATCHDOG_NOTICE, $content_link); } + akismet_clear_cache(); } *************** *** 716,720 **** } } ! else if ($content_type == 'comment') { // This code snippet is based on comment.module::comment_admin_overview_submit() --- 876,880 ---- } } ! else { // comment // This code snippet is based on comment.module::comment_admin_overview_submit() *************** *** 740,743 **** --- 900,905 ---- } } + + akismet_clear_cache(); } |
From: <php...@li...> - 2006-06-06 03:13:08
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8895 Modified Files: akismet.module Log Message: - Fixed a few bugs here and there. - Implemented spam check for content (aka nodes). Spam check for comments was already coded. - A flag (AKISMET_MODE_TEST) has been implemented for not sending real requests to Akismet while testing. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** akismet.module 4 Jun 2006 20:11:40 -0000 1.2 --- akismet.module 5 Jun 2006 02:02:11 -0000 1.3 *************** *** 7,10 **** --- 7,21 ---- /** + * Operate in test mode? + * + * Uncomment one of the following lines, only for developement and testing purposes. + * When the constant is defined, then Akismet requests are NOT really sent, and + * Spam checks always return the value defined here. + */ + define('AKISMET_MODE_TEST', TRUE); + //define('AKISMET_MODE_TEST', FALSE); + + + /** * Implementation of hook_help(). */ *************** *** 191,197 **** $op = arg(3); if ($op == 'publish' || $op == 'unpublish') { ! $callback = 'akismet_switch_content_status'; else if ($op == 'submit-spam' || $op == 'submit-ham') { ! $callback = 'akismet_switch_spam_status'; } if (isset($callback) && akismet_content_exists($content_type, arg(2))) { --- 202,209 ---- $op = arg(3); if ($op == 'publish' || $op == 'unpublish') { ! $callback = 'akismet_callback_set_published_status'; ! } else if ($op == 'submit-spam' || $op == 'submit-ham') { ! $callback = 'akismet_callback_set_spam_status'; } if (isset($callback) && akismet_content_exists($content_type, arg(2))) { *************** *** 254,273 **** * @param string Operation; it can be 'publish' or 'unpublish'. */ ! function akismet_switch_content_status($content_type, $op, $content_id) { ! if ($content_type == 'comment') { ! // Retrieve the comment (existence has been checked in hook_menu). ! $comment = akismet_content_load($content_type, $content_id); ! if ($op == 'publish' && $comment->status == COMMENT_NOT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'publish'); ! } ! else if ($op == 'unpublish' && $comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'unpublish'); ! } ! drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); } ! else if ($content_type == 'node') { ! // @TODO: } - drupal_not_found(); } --- 266,293 ---- * @param string Operation; it can be 'publish' or 'unpublish'. */ ! function akismet_callback_set_published_status($content_type, $content_id, $op) { ! // Load the content (existence has been checked in hook_menu). ! $content = akismet_content_load($content_type, $content_id); ! ! if ($content_type == 'node') { ! $is_published = ($content->status ? TRUE : FALSE); } ! else { // comment ! $is_published = ($content->status == COMMENT_PUBLISHED ? TRUE : FALSE); ! } ! ! if ($op == 'publish' && !$is_published) { ! akismet_content_publish_operation($content_type, $content, 'publish'); ! } ! else if ($op == 'unpublish' && $is_published) { ! akismet_content_publish_operation($content_type, $content, 'unpublish'); ! } ! ! if ($content_type == 'node') { ! drupal_goto("node/$content->nid"); ! } ! else { // comment ! drupal_goto("node/$content->nid", NULL, "comment-$content->cid"); } } *************** *** 281,312 **** * @param string Operation; it can be 'submit-spam' or 'submit-ham'. */ ! function akismet_switch_spam_status($content_type, $op, $content_id) { $is_spam = akismet_content_is_spam($content_type, $content_id); ! if ($content_type == 'comment') { ! // Retrieve the comment (existence has been checked in hook_menu). ! $comment = akismet_content_load($content_type, $content_id); ! // insert or remove the spam marker (publishing/unpublishing if necessary). ! if ($op == 'submit-spam') { ! if (!$is_spam) { ! akismet_content_spam_operation($content_type, $content_id, 'submit-spam'); ! } ! if ($comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'unpublish'); ! } } ! else if ($op == 'submit-ham') { ! if ($is_spam) { ! akismet_content_spam_operation($content_type, $content_id, 'submit-ham'); ! } ! if ($comment->status == COMMENT_NOT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'publish'); ! } } - drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); } ! else if ($content_type == 'node') { ! // @TODO: } - drupal_not_found(); } --- 301,341 ---- * @param string Operation; it can be 'submit-spam' or 'submit-ham'. */ ! function akismet_callback_set_spam_status($content_type, $content_id, $op) { $is_spam = akismet_content_is_spam($content_type, $content_id); ! ! // Load the content (existence has been checked in hook_menu). ! $content = akismet_content_load($content_type, $content_id); ! ! if ($content_type == 'node') { ! $is_published = ($content->status ? TRUE : FALSE); ! } ! else { // comment ! $is_published = ($content->status == COMMENT_PUBLISHED ? TRUE : FALSE); ! } ! ! // insert or remove the spam marker (publishing/unpublishing if necessary). ! if ($op == 'submit-spam') { ! if (!$is_spam) { ! akismet_content_spam_operation($content_type, $content, 'submit-spam'); } ! if ($is_published) { ! akismet_content_publish_operation($content_type, $content, 'unpublish'); } } ! else if ($op == 'submit-ham') { ! if ($is_spam) { ! akismet_content_spam_operation($content_type, $content, 'submit-ham'); ! } ! if (!$is_published) { ! akismet_content_publish_operation($content_type, $content, 'publish'); ! } ! } ! ! if ($content_type == 'node') { ! drupal_goto("node/$content->nid"); ! } ! else { // comment ! drupal_goto("node/$content->nid", NULL, "comment-$content->cid"); } } *************** *** 319,324 **** case 'update': // If Akismet connections are not enabled, we have nothing else to do here. // Also quit asap, if current user has administration permission. ! if (!variable_get('akismet_connection_enabled', 1) || user_access('administer nodes')) { break; } --- 348,357 ---- case 'update': // If Akismet connections are not enabled, we have nothing else to do here. + if (!variable_get('akismet_connection_enabled', 1)) { + break; + } + // Also quit asap, if current user has administration permission. ! if (user_access('administer nodes') && !defined('AKISMET_MODE_TEST')) { break; } *************** *** 326,337 **** // Now, check if it's about a node type that we have not been explicitly requested to check. $check_nodetypes = variable_get('akismet_check_nodetypes', NULL); ! if (is_array($check_nodetypes) && isset($check_nodetypes[$node->type]) && $check_nodetypes[$node->type]) { break; } // Ok, let's send a query to Akismet. ! if (akismet_api_cmd_comment_check(akismet_build_akismet_comment_data('node', $node))) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('node', $node->nid, 'submit-spam'); // Unpublish the node, if necessary. if ($node->status) { --- 359,370 ---- // Now, check if it's about a node type that we have not been explicitly requested to check. $check_nodetypes = variable_get('akismet_check_nodetypes', NULL); ! if (!is_array($check_nodetypes) || !isset($check_nodetypes[$node->type]) || !$check_nodetypes[$node->type]) { break; } // Ok, let's send a query to Akismet. ! if (akismet_api_cmd_comment_check(akismet_prepare_comment_data('node', $node))) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('node', $node, 'submit-spam'); // Unpublish the node, if necessary. if ($node->status) { *************** *** 356,360 **** function akismet_comment(&$comment, $op) { if ($op == 'delete') { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'comment' AND content_id = %d", $content->cid); } } --- 389,393 ---- function akismet_comment(&$comment, $op) { if ($op == 'delete') { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'comment' AND content_id = %d", $comment->cid); } } *************** *** 370,382 **** // Hook into comment edit/reply form. ! if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1) && !user_access('administer comments')) { ! if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { ! // This is the simple hook method, we already have the $cid. ! $form['#submit']['_akismet_comment_form_submit'] = array(); ! } ! else { ! // This is a bit more complex, because the user is creating a new comment, so ! // how do we get the $cid? See comments below, within our own submit callback. ! $form['#submit'] = array('_akismet_comment_form_submit' => array($form['#submit'])); } } --- 403,417 ---- // Hook into comment edit/reply form. ! if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1)) { ! if (!user_access('administer comments') || defined('AKISMET_MODE_TEST')) { ! if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { ! // This is the simple hook method, we already have the $cid. ! $form['#submit']['_akismet_comment_form_submit'] = array(); ! } ! else { ! // This is a bit more complex, because the user is creating a new comment, so ! // how can we get the $cid? See comments below, within our own submit callback. ! $form['#submit'] = array('_akismet_comment_form_submit' => array($form['#submit'])); ! } } } *************** *** 421,429 **** // information that we need to make the Akismet request to check for spam. if ($cid) { ! $comment = akismet_content_load('comment', $cid, TRUE); // If we got a comment, send query to Akismet. ! if ($comment && akismet_api_cmd_comment_check(akismet_build_akismet_comment_data('comment', $comment))) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('comment', $cid, 'submit-spam'); // Unpublish the comment, if necessary. if ($comment->status == COMMENT_PUBLISHED) { --- 456,464 ---- // information that we need to make the Akismet request to check for spam. if ($cid) { ! $comment = akismet_content_load('comment', $cid); // If we got a comment, send query to Akismet. ! if ($comment && akismet_api_cmd_comment_check(akismet_prepare_comment_data('comment', $comment))) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('comment', $comment, 'submit-spam'); // Unpublish the comment, if necessary. if ($comment->status == COMMENT_PUBLISHED) { *************** *** 474,501 **** * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. ! * @param boolen Whether to load all possible comment data or only the basic record (optional, defaults to FALSE). ! * @return mixed An object with requested content or FALSE on failure. */ ! function akismet_content_load($content_type, $content_id, $alldata = FALSE) { if ($content_type == 'node') { ! if ($alldata) { ! $content = node_load($content_id); ! if (empty($content->nid)) { ! $content = FALSE; ! } ! } ! else { ! $content = db_fetch_object(db_query('SELECT * FROM {node} WHERE nid = %d', $content_id)); } } else if ($content_type == 'comment') { ! if ($alldata) { ! $content = db_fetch_object(db_query(db_rewrite_sql('SELECT c.*, u.name AS registered_name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', 'c'), $content_id)); ! if ($content->uid) { ! $content->name = $content->registered_name; ! } ! } ! else { ! $content = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $content_id)); } } --- 509,525 ---- * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. ! * @return mixed An object with requested content; FALSE on failure. */ ! function akismet_content_load($content_type, $content_id) { if ($content_type == 'node') { ! $content = node_load($content_id); ! if (empty($content->nid)) { ! $content = FALSE; } } else if ($content_type == 'comment') { ! $content = db_fetch_object(db_query(db_rewrite_sql('SELECT c.*, u.name AS registered_name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', 'c'), $content_id)); ! if ($content->uid) { ! $content->name = $content->registered_name; } } *************** *** 509,531 **** * Mark content as spam or remove the mark. * - * A previous check needs to be made in order to see if content is already marked as spam or not. - * * @param string Content type; can be either 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. * @param string Operation; it can be 'submit-spam' or 'submit-ham'. */ ! function akismet_content_spam_operation($content_type, $content_id, $op) { ! if ($op == 'spam') { db_query("INSERT INTO {akismet_spam_marks} (content_type, content_id, spam_created) VALUES ('%s', %d, %d)", $content_type, $content_id, time()); if (variable_get('akismet_connection_enabled', 1)) { ! // @TODO: Submit spam!? } } ! else if ($op == 'ham') { db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id); if (variable_get('akismet_connection_enabled', 1)) { ! // @TODO: Submit ham!? } } } --- 533,577 ---- * Mark content as spam or remove the mark. * * @param string Content type; can be either 'node' or 'comment'. ! * @param object Content object. * @param string Operation; it can be 'submit-spam' or 'submit-ham'. */ ! function akismet_content_spam_operation($content_type, $content, $op) { ! if ($content_type == 'node') { ! $content_id = $content->nid; ! $content_title = $content->title; ! $content_link = l(t('view'), "node/$content->nid"); ! } ! else { // comment ! $content_id = $content->cid; ! $content_title = $content->subject; ! $content_link = l(t('view'), "node/$content->nid", NULL, NULL, "comment-$content->cid"); ! } ! ! if ($op == 'submit-spam') { db_query("INSERT INTO {akismet_spam_marks} (content_type, content_id, spam_created) VALUES ('%s', %d, %d)", $content_type, $content_id, time()); + if (variable_get('akismet_connection_enabled', 1)) { ! akismet_api_cmd_submit_spam(akismet_prepare_comment_data($content_type, $content)); ! $action = ($content_type == 'node' ? t('Content submitted as spam') : t('Comment submitted as spam')); ! } ! else { ! $action = ($content_type == 'node' ? t('Content marked as spam') : t('Comment marked as spam')); } } ! else { // submit-ham db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id); + if (variable_get('akismet_connection_enabled', 1)) { ! akismet_api_cmd_submit_ham(akismet_prepare_comment_data($content_type, $content)); ! $action = ($content_type == 'node' ? t('Content submitted as ham') : t('Comment submitted as ham')); ! } ! else { ! $action = ($content_type == 'node' ? t('Content marked as ham') : t('Comment marked as ham')); } } + + // Add an entry to the watchdog log. + watchdog('content', t('%action: %title', array('%action' => $action, '%title' => theme('placeholder', $content_title))), WATCHDOG_NOTICE, $content_link); } *************** *** 542,559 **** // Only the node record is updated, no other hooks are invoked. - // Cache operations in case we need to come here more than once per request. - static $node_operations = FALSE; - if (!$node_operations) { - $node_operations = node_operations(); - } - - // extract the appropriate database query operation - $query = $node_operations[$op][1]; // perform the update action, then refresh node statistics ! db_query($query, $content->nid); // Add an entry to the watchdog log. ! $action = ($op == 'unpublish' ? t('unpublished') : t('published')); ! watchdog('content', t('Content %action: %title', array('%action' => $action, '%subject' => theme('placeholder', $content->title))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $comment->nid)); } else if ($content_type == 'comment') { --- 588,597 ---- // Only the node record is updated, no other hooks are invoked. // perform the update action, then refresh node statistics ! db_query('UPDATE {node} SET status = %d WHERE nid = %d', ($op == 'publish' ? 1 : 0), $content->nid); // Add an entry to the watchdog log. ! $action = ($op == 'publish' ? t('Content published') : t('Content unpublished')); ! watchdog('content', t('%action: %title', array('%action' => $action, '%title' => theme('placeholder', $content->title))), WATCHDOG_NOTICE, l(t('view'), "node/$content->nid")); } else if ($content_type == 'comment') { *************** *** 577,582 **** // Add an entry to the watchdog log. ! $action = ($op == 'unpublish' ? t('unpublished') : t('published')); ! watchdog('content', t('Comment %action: %subject', array('%action' => $action, '%subject' => theme('placeholder', $content->subject))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $content->nid, NULL, NULL, 'comment-'. $content->cid)); } } --- 615,620 ---- // Add an entry to the watchdog log. ! $action = ($op == 'publish' ? t('Comment published') : t('Comment unpublished')); ! watchdog('content', t('%action: %subject', array('%action' => $action, '%subject' => theme('placeholder', $content->subject))), WATCHDOG_NOTICE, l(t('view'), "node/$content->nid", NULL, NULL, "comment-$content->cid")); } } *************** *** 589,593 **** * @return array */ ! function akismet_build_akismet_comment_data($content_type, $content) { // Prepare data that is common to nodes/comments. $comment_data = array( --- 627,631 ---- * @return array */ ! function akismet_prepare_comment_data($content_type, $content) { // Prepare data that is common to nodes/comments. $comment_data = array( *************** *** 637,640 **** --- 675,681 ---- */ function akismet_api_cmd_verify_key($key) { + if (defined('AKISMET_MODE_TEST')) { + return TRUE; + } global $base_url; $request = "key=$key&blog=$base_url"; *************** *** 646,655 **** * Akismet API: Comment Check api-key.rest.akismet.com/1.1/comment-check * ! * @param array Comment data; see function akismet_build_akismet_comment_data(). * @return boolean TRUE if the comment IS spam; FALSE otherwise. */ function akismet_api_cmd_comment_check($comment_data) { ! $comment_data = array_merge(_akismet_api_build_server_data(), $comment_data); ! $query_string = _akismet_api_get_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); --- 687,699 ---- * Akismet API: Comment Check api-key.rest.akismet.com/1.1/comment-check * ! * @param array Comment data; see function akismet_prepare_comment_data(). * @return boolean TRUE if the comment IS spam; FALSE otherwise. */ function akismet_api_cmd_comment_check($comment_data) { ! if (defined('AKISMET_MODE_TEST')) { ! return AKISMET_MODE_TEST; ! } ! $comment_data = array_merge(_akismet_api_prepare_request_data(), $comment_data); ! $query_string = _akismet_api_build_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); *************** *** 660,667 **** * Akismet API: Submit Spam api-key.rest.akismet.com/1.1/submit-spam * ! * @param array Comment data; see function akismet_build_akismet_comment_data(). */ function akismet_api_cmd_submit_spam($comment_data) { ! $query_string = _akismet_api_get_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-spam'); --- 704,714 ---- * Akismet API: Submit Spam api-key.rest.akismet.com/1.1/submit-spam * ! * @param array Comment data; see function akismet_prepare_comment_data(). */ function akismet_api_cmd_submit_spam($comment_data) { ! if (defined('AKISMET_MODE_TEST')) { ! return; ! } ! $query_string = _akismet_api_build_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-spam'); *************** *** 671,678 **** * Akismet API: Submit Ham api-key.rest.akismet.com/1.1/submit-ham * ! * @param array Comment data; see function akismet_build_akismet_comment_data(). */ function akismet_api_cmd_submit_ham($comment_data) { ! $query_string = _akismet_api_get_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-ham'); --- 718,728 ---- * Akismet API: Submit Ham api-key.rest.akismet.com/1.1/submit-ham * ! * @param array Comment data; see function akismet_prepare_comment_data(). */ function akismet_api_cmd_submit_ham($comment_data) { ! if (defined('AKISMET_MODE_TEST')) { ! return; ! } ! $query_string = _akismet_api_build_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-ham'); *************** *** 680,688 **** /** ! * Prepare $_SERVER data that is to be sent along akismet requests. * ! * @return array */ ! function _akismet_api_build_server_data() { // You may add more elements here, but they are often related to internal server // data that makes little sense to check whether a comment is spam or not. --- 730,738 ---- /** ! * Prepare user request data for Akismet requests. * ! * @return array Relevant information extracted from $_SERVER superglobal. */ ! function _akismet_api_prepare_request_data() { // You may add more elements here, but they are often related to internal server // data that makes little sense to check whether a comment is spam or not. *************** *** 723,732 **** /** ! * Convert an associative array into a query string formatted according to akismet rules. * * @param array * @return string */ ! function _akismet_api_get_query_string($array) { global $base_url; $string = 'blog='. $base_url . base_path(); --- 773,782 ---- /** ! * Build query string for Akismet request. * * @param array * @return string */ ! function _akismet_api_build_query_string($array) { global $base_url; $string = 'blog='. $base_url . base_path(); |
From: <php...@li...> - 2006-06-06 01:50:50
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11669 Modified Files: akismet.module Log Message: - Reviewed descriptions in the settings panel. - Implemented queue for manual moderation when Akismet is down. - Reviewed test mode option. - Please, also see TODO notes. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** akismet.module 5 Jun 2006 02:02:11 -0000 1.3 --- akismet.module 5 Jun 2006 13:32:39 -0000 1.4 *************** *** 2,18 **** // $Id$ ! /************************************************************\ ! WARNING: Module is in development! See @TODO notes. ! \************************************************************/ /** ! * Operate in test mode? ! * ! * Uncomment one of the following lines, only for developement and testing purposes. ! * When the constant is defined, then Akismet requests are NOT really sent, and ! * Spam checks always return the value defined here. */ ! define('AKISMET_MODE_TEST', TRUE); ! //define('AKISMET_MODE_TEST', FALSE); --- 2,26 ---- // $Id$ ! /********************************************************************************\ ! WARNING: Module is in development! ! ! @TODO: Think about and implement spam moderation queue. ! @TODO: Review the help page. ! @TODO: Implement spam counter (and maybe a themable block?). ! @TODO: Implement an opt-in option for administrators to e-mail them when content ! is posted (maybe for all posts, or for detected spam or nothing). ! ! \********************************************************************************/ /** ! * Akismet API constants. */ ! define('AKISMET_API_HOST', 'rest.akismet.com'); ! define('AKISMET_API_PORT', 80); ! define('AKISMET_API_VERSION', '1.1'); ! define('AKISMET_USERAGENT', 'Drupal/4.7 | akismet.module/1.0'); ! define('AKISMET_API_RESULT_IS_SPAM', 1); ! define('AKISMET_API_RESULT_IS_HAM', 2); ! define('AKISMET_API_RESULT_ERROR', -1); *************** *** 35,39 **** case 'admin/help#akismet': $output = t('<p>In order to use the <a href="%akismet">Akismet Service</a>, you need a <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.</p> ! <p>The <em>akismet module</em> can be <a href="%akismet-settings">configured</a> to automatically check for spam posted in content (nodes and/or comments). You can use <a href="%access-control">access control</a> to grant the <em>%no-check-perm</em> permission to <em>user roles</em> of your choice.</p> <p>Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. There is <a href="%akismet-settings">an option</a> that allows you to specify how long this information will be kept in the database. <em>Spam</em> older than a specified interval will be automatically removed. Requires crontab.</p> <p>Automatic spam detection can be enabled or disabled by content type and/or comments. In addition to this, the <em>akismet module</em> makes it easy for <em>content administrators</em> to manually <em>publish</em>/<em>unpublish</em> content and <em>mark</em>/<em>unmark</em> content as spam, from links available at the bottom of content.</p> --- 43,47 ---- case 'admin/help#akismet': $output = t('<p>In order to use the <a href="%akismet">Akismet Service</a>, you need a <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.</p> ! <p>The <em>akismet module</em> may automatically check for spam posted in content (nodes and/or comments) by any user, except node or comment administrators respectively. It is also possible, from the <a href="%access-control">access control</a> panel, to grant <em>%no-check-perm</em> permission to <em>user roles</em> of your choice.</p> <p>Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. There is <a href="%akismet-settings">an option</a> that allows you to specify how long this information will be kept in the database. <em>Spam</em> older than a specified interval will be automatically removed. Requires crontab.</p> <p>Automatic spam detection can be enabled or disabled by content type and/or comments. In addition to this, the <em>akismet module</em> makes it easy for <em>content administrators</em> to manually <em>publish</em>/<em>unpublish</em> content and <em>mark</em>/<em>unmark</em> content as spam, from links available at the bottom of content.</p> *************** *** 51,55 **** case 'admin/settings/akismet': $output = t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p> ! <p>This panel allows you to configure all <em>akismet module</em> options. Please, refer to the <a href="%help-page">help page</a> for further information.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', --- 59,63 ---- case 'admin/settings/akismet': $output = t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p> ! <p>This panel allows you to configure all <em>akismet module</em> options. For further information, please consult the <a href="%help-page">help page</a> of the module.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', *************** *** 106,110 **** '#size' => 30, '#maxlength' => 60, '#default_value' => $akismet_wpapikey, ! '#description' => t('Please, enter here your <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Note that this information is required in order to use the <a href="%akismet">Akismet Service</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.', array( '%wpapikey' => 'http://wordpress.com/api-keys/', --- 114,118 ---- '#size' => 30, '#maxlength' => 60, '#default_value' => $akismet_wpapikey, ! '#description' => t('Please, enter here your <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">WordPress.com</a>. Note that this information is required in order to use the <a href="%akismet">Akismet Service</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.', array( '%wpapikey' => 'http://wordpress.com/api-keys/', *************** *** 137,190 **** ); ! $form['content'] = array( ! '#type' => 'fieldset', '#title' => t('Content settings'), '#collapsible' => TRUE, '#collapsed' => TRUE ); if (module_exist('comment')) { ! $form['content']['comment_options'] = array( ! '#type' => 'fieldset', '#title' => t('Comment options') ); ! $form['content']['comment_options']['akismet_check_comments'] = array( '#type' => 'radios', '#title' => t('Check for spam in comments'), '#options' => $enable_options, '#default_value' => variable_get('akismet_check_comments', 1), ! '#description' => t('Enable this option to automatically check for spam in comments. Regardless of this option, users with <em>%admin-comments</em> permission are still allowed to manually <em>submit spam</em>/<em>ham</em> (or <em>mark</em>/<em>unmark</em> when the <em>Akismet connections</em> options has been <em>disabled</em> above) from the links at the bottom of comments.', array( '%admin-comments' => t('administer comments') )) ); ! $form['content']['comment_options']['akismet_comment_links_enabled'] = array( '#type' => 'radios', ! '#title' => t('Links in comments'), '#options' => $enable_options, ! '#default_value' => variable_get('akismet_comment_links_enabled', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links in comments for operations such as <em>publish</em>, <em>unpublish</em>, <em>submit spam</em>, <em>submit ham</em>, etc. Note that <em>mark as ...</em> will be used (instead of <em>submit ...</em>) when the <em>Akismet connections</em> option has been <em>disabled</em> above.') ); } - $form['content']['node_options'] = array( - '#type' => 'fieldset', '#title' => t('Node options') - ); - $types = node_get_types(); - $form['content']['node_options']['akismet_check_nodetypes'] = array( - '#type' => 'checkboxes', - '#title' => t('Check for spam in these content type(s)'), - '#options' => $types, - '#default_value' => variable_get('akismet_check_nodetypes', NULL), - '#description' => t('Select the content types that are to be automatically checked for spam. Note that this options might only be useful when non administrators are allowed to create content. Regardless of these options, users with <em>%admin-nodes</em> permission are still allowed to manually <em>submit spam</em>/<em>ham</em> (or <em>mark</em>/<em>unmark</em> when the <em>Akismet connections</em> options has been <em>disabled</em> above) from the links at the bottom of nodes.', - array( - '%admin-nodes' => t('administer nodes') - )) - ); - $form['content']['node_options']['akismet_node_links_enabled'] = array( - '#type' => 'radios', - '#title' => t('Links in nodes'), - '#options' => $enable_options, - '#default_value' => variable_get('akismet_node_links_enabled', 0), - '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links in nodes for operations such as <em>publish</em>, <em>unpublish</em>, <em>submit spam</em>, <em>submit ham</em>, etc. Note that <em>mark as ...</em> will be used (instead of <em>submit ...</em>) when the <em>Akismet connections</em> option has been <em>disabled</em> above.') - ); - return $form; } --- 145,231 ---- ); ! $form['node_options'] = array( ! '#type' => 'fieldset', '#title' => t('Node options'), '#collapsible' => TRUE, '#collapsed' => TRUE ); + $types = node_get_types(); + $form['node_options']['akismet_check_nodetypes'] = array( + '#type' => 'checkboxes', + '#title' => t('Check for spam in these node types'), + '#options' => $types, + '#default_value' => variable_get('akismet_check_nodetypes', NULL), + '#description' => t('Use this option to <em>enable</em> or <em>disable</em> spam check for nodes of types specified here. When this option is enabled, a request will be sent to the <a href="%akismet">Akismet Service</a>, in real time. If the <a href="%akismet">Akismet Service</a> was down, nodes would simply be queued for manual moderation. Users with <em>%admin-nodes</em> permission are exempt from this check.', + array( + '%akismet' => 'http://akismet.com', + '%admin-nodes' => t('administer nodes') + )) + ); + $form['node_options']['akismet_node_publish_links'] = array( + '#type' => 'radios', + '#title' => t('Show publish/unpublish links'), + '#options' => $enable_options, + '#default_value' => variable_get('akismet_node_publish_links', 0), + '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>publish</em>/<em>unpublish</em> operations in nodes. If enabled, these links will only be displayed to users with <em>%admin-nodes</em> permission.', + array( + '%admin-nodes' => t('administer nodes') + )) + ); + $form['node_options']['akismet_node_spam_links'] = array( + '#type' => 'radios', + '#title' => t('Show submit spam/ham links'), + '#options' => $enable_options, + '#default_value' => variable_get('akismet_node_spam_links', 0), + '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>submit spam</em>/<em>ham</em> operations in nodes. If enabled, these links will only be displayed to users with <em>%admin-nodes</em> permission.', + array( + '%admin-nodes' => t('administer nodes') + )) + .'<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use these links to submit missed spam and false positives (ham), otherwise Akismet will never learn from its mistakes. Thank you.', + array( + '%akismet' => 'http://akismet.com' + )) + ); if (module_exist('comment')) { ! $form['comment_options'] = array( ! '#type' => 'fieldset', '#title' => t('Comment options'), ! '#collapsible' => TRUE, '#collapsed' => TRUE ); ! $form['comment_options']['akismet_check_comments'] = array( '#type' => 'radios', '#title' => t('Check for spam in comments'), '#options' => $enable_options, '#default_value' => variable_get('akismet_check_comments', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> spam check for comments. When this option is enabled, a request will be sent to the <a href="%akismet">Akismet Service</a>, in real time. If the <a href="%akismet">Akismet Service</a> was down, comments would simply be queued for manual moderation. Users with <em>%admin-comments</em> permission are exempt from this check.', array( + '%akismet' => 'http://akismet.com', '%admin-comments' => t('administer comments') )) ); ! $form['comment_options']['akismet_comment_publish_links'] = array( '#type' => 'radios', ! '#title' => t('Show publish/unpublish links'), '#options' => $enable_options, ! '#default_value' => variable_get('akismet_comment_publish_links', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>publish</em>/<em>unpublish</em> operations in comments. If enabled, these links will only be displayed to users with <em>%admin-comments</em> permission.', ! array( ! '%admin-comments' => t('administer comments') ! )) ! ); ! $form['comment_options']['akismet_comment_spam_links'] = array( ! '#type' => 'radios', ! '#title' => t('Show submit spam/ham links'), ! '#options' => $enable_options, ! '#default_value' => variable_get('akismet_comment_spam_links', 1), ! '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links for <em>submit spam</em>/<em>ham</em> operations in comments. If enabled, these links will only be displayed to users with <em>%admin-comments</em> permission.', ! array( ! '%admin-comments' => t('administer comments') ! )) ! .'<br />'. t('<strong>Note:</strong> To interact fully with the <a href="%akismet">Akismet Service</a> you really should try putting data back into the system as well as just taking it out. If it is at all possible, please use these links to submit missed spam and false positives (ham), otherwise Akismet will never learn from its mistakes. Thank you.', ! array( ! '%akismet' => 'http://akismet.com' ! )) ); } return $form; } *************** *** 224,256 **** function akismet_link($type, $content = 0, $main = 0) { $links = array(); ! if ($type == 'comment' && user_access('administer comments') && variable_get('akismet_comment_links_enabled', 1)) { ! if ($content->status == COMMENT_PUBLISHED) { ! $links[] = l(t('unpublish'), "akismet/comment/$content->cid/unpublish"); ! } ! else if ($content->status == COMMENT_NOT_PUBLISHED) { ! $links[] = l(t('publish'), "akismet/comment/$content->cid/publish"); } ! if (variable_get('akismet_connection_enabled', 1)) { ! if (akismet_content_is_spam('comment', $content->cid)) { ! $links[] = l(t('submit ham'), "akismet/comment/$content->cid/submit-ham"); } else { ! $links[] = l(t('submit spam'), "akismet/comment/$content->cid/submit-spam"); } } } ! else if ($type == 'node' && user_access('administer nodes') && variable_get('akismet_node_links_enabled', 0)) { ! if ($content->status) { ! $links[] = l(t('unpublish'), "akismet/node/$content->nid/unpublish"); ! } ! else { ! $links[] = l(t('publish'), "akismet/node/$content->nid/publish"); } ! if (variable_get('akismet_connection_enabled', 1)) { ! if (akismet_content_is_spam('node', $content->nid)) { ! $links[] = l(t('submit ham'), "akismet/node/$content->nid/submit-ham"); } else { ! $links[] = l(t('submit spam'), "akismet/node/$content->nid/submit-spam"); } } --- 265,301 ---- function akismet_link($type, $content = 0, $main = 0) { $links = array(); ! if ($type == 'node' && user_access('administer nodes')) { ! if (variable_get('akismet_node_publish_links', 0)) { ! if ($content->status) { ! $links[] = l(t('unpublish'), "akismet/node/$content->nid/unpublish"); ! } ! else { ! $links[] = l(t('publish'), "akismet/node/$content->nid/publish"); ! } } ! if (variable_get('akismet_node_spam_links', 0)) { ! if (akismet_content_is_spam('node', $content->nid)) { ! $links[] = l((variable_get('akismet_connection_enabled', 1) ? t('submit ham') : t('mark as ham')), "akismet/node/$content->nid/submit-ham"); } else { ! $links[] = l((variable_get('akismet_connection_enabled', 1) ? t('submit spam') : t('mark as spam')), "akismet/node/$content->nid/submit-spam"); } } } ! else if ($type == 'comment' && user_access('administer comments')) { ! if (variable_get('akismet_comment_publish_links', 1)) { ! if ($content->status == COMMENT_PUBLISHED) { ! $links[] = l(t('unpublish'), "akismet/comment/$content->cid/unpublish"); ! } ! else if ($content->status == COMMENT_NOT_PUBLISHED) { ! $links[] = l(t('publish'), "akismet/comment/$content->cid/publish"); ! } } ! if (variable_get('akismet_comment_spam_links', 1)) { ! if (akismet_content_is_spam('comment', $content->cid)) { ! $links[] = l((variable_get('akismet_connection_enabled', 1) ? t('submit ham') : t('mark as ham')), "akismet/comment/$content->cid/submit-ham"); } else { ! $links[] = l((variable_get('akismet_connection_enabled', 1) ? t('submit spam') : t('mark as spam')), "akismet/comment/$content->cid/submit-spam"); } } *************** *** 353,357 **** // Also quit asap, if current user has administration permission. ! if (user_access('administer nodes') && !defined('AKISMET_MODE_TEST')) { break; } --- 398,402 ---- // Also quit asap, if current user has administration permission. ! if (user_access('administer nodes')) { break; } *************** *** 364,379 **** // Ok, let's send a query to Akismet. ! if (akismet_api_cmd_comment_check(akismet_prepare_comment_data('node', $node))) { ! // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('node', $node, 'submit-spam'); // Unpublish the node, if necessary. if ($node->status) { akismet_content_publish_operation('node', $node, 'unpublish'); } // Since users won't see their content published, show them a polite explanation on why. $content_type_name = node_get_name($node); drupal_set_message(t('Your %content-type-name has been queued for moderation by site administrators and will be published after approval.', array('%content-type-name' => $content_type_name))); // Add an entry to the watchdog log. ! watchdog('content', t('Spam detected by akismet in %content-type-name: %title', array('%content-type-name' => $content_type_name, '%title' => theme('placeholder', $node->title))), WATCHDOG_WARNING, l(t('view'), "node/$node->nid")); } break; --- 409,435 ---- // Ok, let's send a query to Akismet. ! $akismet_api_result = akismet_api_cmd_comment_check(akismet_prepare_comment_data('node', $node)); ! if ($akismet_api_result != AKISMET_API_RESULT_IS_HAM) { ! if ($akismet_api_result == AKISMET_API_RESULT_IS_SPAM) { ! // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('node', $node, 'submit-spam'); ! } ! // Unpublish the node, if necessary. if ($node->status) { akismet_content_publish_operation('node', $node, 'unpublish'); } + // Since users won't see their content published, show them a polite explanation on why. $content_type_name = node_get_name($node); drupal_set_message(t('Your %content-type-name has been queued for moderation by site administrators and will be published after approval.', array('%content-type-name' => $content_type_name))); + // Add an entry to the watchdog log. ! if ($akismet_api_result == AKISMET_API_RESULT_ERROR) { ! watchdog('content', t('Akismet service seems to be down, %content-type-name queued for manual approval: %title', array('%content-type-name' => $content_type_name, '%title' => theme('placeholder', $node->title))), WATCHDOG_WARNING, l(t('view'), "node/$node->nid")); ! } ! else { ! watchdog('content', t('Spam detected by Akismet in %content-type-name: %title', array('%content-type-name' => $content_type_name, '%title' => theme('placeholder', $node->title))), WATCHDOG_WARNING, l(t('view'), "node/$node->nid")); ! } } break; *************** *** 404,408 **** // Hook into comment edit/reply form. if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1)) { ! if (!user_access('administer comments') || defined('AKISMET_MODE_TEST')) { if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { // This is the simple hook method, we already have the $cid. --- 460,464 ---- // Hook into comment edit/reply form. if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1)) { ! if (!user_access('administer comments')) { if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { // This is the simple hook method, we already have the $cid. *************** *** 458,472 **** $comment = akismet_content_load('comment', $cid); // If we got a comment, send query to Akismet. ! if ($comment && akismet_api_cmd_comment_check(akismet_prepare_comment_data('comment', $comment))) { ! // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('comment', $comment, 'submit-spam'); ! // Unpublish the comment, if necessary. ! if ($comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation('comment', $comment, 'unpublish'); } - // Since users won't see their replies published, show them a polite explanation on why. - drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.')); - // Add an entry to the watchdog log. - watchdog('content', t('Spam detected by akismet in comment: %subject', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); } } --- 514,541 ---- $comment = akismet_content_load('comment', $cid); // If we got a comment, send query to Akismet. ! if ($comment) { ! $akismet_api_result = akismet_api_cmd_comment_check(akismet_prepare_comment_data('comment', $comment)); ! if ($akismet_api_result != AKISMET_API_RESULT_IS_HAM) { ! if ($akismet_api_result == AKISMET_API_RESULT_IS_SPAM) { ! // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('comment', $comment, 'submit-spam'); ! } ! ! // Unpublish the comment, if necessary. ! if ($comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation('comment', $comment, 'unpublish'); ! } ! ! // Since users won't see their replies published, show them a polite explanation on why. ! drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.')); ! ! // Add an entry to the watchdog log. ! if ($akismet_api_result == AKISMET_API_RESULT_ERROR) { ! watchdog('content', t('Akismet service seems to be down, comment queued for manual approval: %subject', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); ! } ! else { ! watchdog('content', t('Spam detected by Akismet in comment: %subject', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); ! } } } } *************** *** 663,671 **** \************************************************************/ - define('AKISMET_API_HOST', 'rest.akismet.com'); - define('AKISMET_API_PORT', 80); - define('AKISMET_API_VERSION', '1.1'); - define('AKISMET_USERAGENT', 'Drupal/4.7 | akismet.module/1.0'); - /** * Akismet API: Key Verification rest.akismet.com/1.1/verify key --- 732,735 ---- *************** *** 675,681 **** */ function akismet_api_cmd_verify_key($key) { - if (defined('AKISMET_MODE_TEST')) { - return TRUE; - } global $base_url; $request = "key=$key&blog=$base_url"; --- 739,742 ---- *************** *** 688,696 **** * * @param array Comment data; see function akismet_prepare_comment_data(). ! * @return boolean TRUE if the comment IS spam; FALSE otherwise. */ function akismet_api_cmd_comment_check($comment_data) { ! if (defined('AKISMET_MODE_TEST')) { ! return AKISMET_MODE_TEST; } $comment_data = array_merge(_akismet_api_prepare_request_data(), $comment_data); --- 749,757 ---- * * @param array Comment data; see function akismet_prepare_comment_data(). ! * @return integer See constants AKISMET_API_RESULT_xxx. */ function akismet_api_cmd_comment_check($comment_data) { ! if (!variable_get('akismet_connection_enabled', 1)) { ! return FALSE; } $comment_data = array_merge(_akismet_api_prepare_request_data(), $comment_data); *************** *** 698,702 **** $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); ! return ('true' == $response[1] ? TRUE : FALSE); } --- 759,769 ---- $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); ! if ('true' == $response[1]) { ! return AKISMET_API_RESULT_IS_SPAM; ! } ! if ('false' == $response[1]) { ! return AKISMET_API_RESULT_IS_HAM; ! } ! return AKISMET_API_RESULT_ERROR; } *************** *** 707,711 **** */ function akismet_api_cmd_submit_spam($comment_data) { ! if (defined('AKISMET_MODE_TEST')) { return; } --- 774,778 ---- */ function akismet_api_cmd_submit_spam($comment_data) { ! if (!variable_get('akismet_connection_enabled', 1)) { return; } *************** *** 721,725 **** */ function akismet_api_cmd_submit_ham($comment_data) { ! if (defined('AKISMET_MODE_TEST')) { return; } --- 788,792 ---- */ function akismet_api_cmd_submit_ham($comment_data) { ! if (!variable_get('akismet_connection_enabled', 1)) { return; } |
From: <php...@li...> - 2006-06-06 01:49:22
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv522 Modified Files: akismet.module Log Message: Today I've been working a bit more here. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** akismet.module 4 Jun 2006 00:52:45 -0000 1.1 --- akismet.module 4 Jun 2006 20:11:40 -0000 1.2 *************** *** 2,7 **** // $Id$ ! define('AKISMET_CONTENT_STATUS_SPAM', 1); ! define('AKISMET_CONTENT_STATUS_HAM' , 2); /** --- 2,8 ---- // $Id$ ! /************************************************************\ ! WARNING: Module is in development! See @TODO notes. ! \************************************************************/ /** *************** *** 59,204 **** /** ! * Implementation of hook_menu(). ! */ ! function akismet_menu($may_cache) { ! $items = array(); ! if (!$may_cache) { ! // Paths may look like 'akismet/content_type/operation/content_id' ! if (arg(0) == 'akismet' && is_numeric(arg(3))) { ! $content_type = arg(1); ! if ($content_type == 'comment' && module_exist('comment')) { ! $op = arg(2); ! if ($op == 'publish' || $op == 'unpublish') { ! if (_akismet_comment_exists(arg(3))) { ! $items[] = array('path' => 'akismet', 'title' => t('switch comment status'), ! 'callback' => 'akismet_switch_content_status', 'access' => user_access('administer comments'), ! 'type' => MENU_CALLBACK); ! } ! } ! else if ($op == 'submit-spam' || $op == 'submit-ham') { ! if (_akismet_comment_exists(arg(3))) { ! $items[] = array('path' => 'akismet', 'title' => t('switch spam status'), ! 'callback' => 'akismet_switch_spam_status', 'access' => user_access('administer comments'), ! 'type' => MENU_CALLBACK); ! } ! } ! } ! else if ($content_type == 'node') { ! // @TODO: ! } ! } ! } ! return $items; ! } ! ! /** ! * Implementation of hook_link(). ! */ ! function akismet_link($type, $content = 0, $main = 0) { ! $links = array(); ! if ($type == 'comment' && user_access('administer comments') && variable_get('akismet_comment_links_enabled', 1)) { ! if ($content->status == COMMENT_PUBLISHED) { ! $links[] = l(t('unpublish'), "akismet/comment/unpublish/$content->cid"); ! } ! else if ($content->status == COMMENT_NOT_PUBLISHED) { ! $links[] = l(t('publish'), "akismet/comment/publish/$content->cid"); ! } ! if (variable_get('akismet_connection_enabled', 1)) { ! } ! if (akismet_is_content_spam('comment', $content->cid)) { ! $links[] = l(t('submit ham'), "akismet/comment/submit-ham/$content->cid"); ! } ! else { ! $links[] = l(t('submit spam'), "akismet/comment/submit-spam/$content->cid"); ! } ! } ! else if ($type == 'node' && user_access('administer nodes') && variable_get('akismet_node_links_enabled', 0)) { ! // @TODO: Implement node links ...et al. ! } ! return $links; ! } ! ! /** ! * Menu callback; publish/unpublish content. ! */ ! function akismet_switch_content_status($content_type, $op, $content_id) { ! if ($content_type == 'comment') { ! // Retrieve the comment (existence has been checked in hook_menu). ! $comment = _akismet_comment_load($content_id); ! if ($op == 'publish' && $comment->status == COMMENT_NOT_PUBLISHED) { ! akismet_comment_operation($content_id, 'publish'); ! } ! else if ($op == 'unpublish' && $comment->status == COMMENT_PUBLISHED) { ! akismet_comment_operation($content_id, 'unpublish'); ! } ! drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); ! } ! else if ($content_type == 'node') { ! // @TODO: ! } ! drupal_not_found(); ! } ! ! /** ! * Menu callback; mark/unmark content as spam. ! * ! * When content is marked as spam, it is also unpublished (if necessary) and vice-versa. ! */ ! function akismet_switch_spam_status($content_type, $op, $content_id) { ! $is_spam = akismet_is_content_spam($content_type, $content_id); ! if ($content_type == 'comment') { ! // Retrieve the comment (existence has been checked in hook_menu). ! $comment = _akismet_comment_load($content_id); ! // insert or remove the spam marker (publishing/unpublishing if necessary). ! if ($op == 'submit-spam') { ! if (!$is_spam) { ! akismet_set_content_status($content_type, $content_id, AKISMET_CONTENT_STATUS_SPAM); ! } ! if ($comment->status == COMMENT_PUBLISHED) { ! akismet_comment_operation($content_id, 'unpublish'); ! } ! } ! else if ($op == 'submit-ham') { ! if ($is_spam) { ! akismet_set_content_status($content_type, $content_id, AKISMET_CONTENT_STATUS_HAM); ! } ! if ($comment->status == COMMENT_NOT_PUBLISHED) { ! akismet_comment_operation($content_id, 'publish'); ! } ! } ! drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); ! } ! else if ($content_type == 'node') { ! // @TODO: ! } ! drupal_not_found(); ! } ! ! /** ! * Check if specified content is marked as spam. ! * ! * @param string Content type; can be either 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! */ ! function akismet_is_content_spam($content_type, $content_id) { ! return db_result(db_query("SELECT 1 FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id)); ! } ! ! /** ! * Mark content as spam or remove the mark. ! * ! * A previous check needs to be made in order to see if content is already marked as spam or not. ! * ! * @param string Content type; can be either 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! * @param integer Content Status; it can be AKISMET_CONTENT_STATUS_SPAM or AKISMET_CONTENT_STATUS_HAM. */ ! function akismet_set_content_status($content_type, $content_id, $status) { ! if ($status == AKISMET_CONTENT_STATUS_HAM) { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id); ! } ! else if ($status == AKISMET_CONTENT_STATUS_SPAM) { ! db_query("INSERT INTO {akismet_spam_marks} (content_type, content_id, spam_created) VALUES ('%s', %d, %d)", $content_type, $content_id, time()); ! } } --- 60,68 ---- /** ! * Implementation of hook_cron(). */ ! function akismet_cron() { ! // Remove spam older than... ! db_query('DELETE FROM {akismet_spam_marks} WHERE spam_created < %d', time() - variable_get('akismet_remove_spam_interval', 259200)); } *************** *** 316,355 **** /** ! * Implementation of hook_cron(). */ ! function akismet_cron() { ! // Remove spam older than... ! db_query('DELETE FROM {akismet_spam_marks} WHERE spam_created < %d', time() - variable_get('akismet_remove_spam_interval', 259200)); } /** ! * Implementation of hook_form_alter(). */ ! function akismet_form_alter($form_id, &$form) { ! global $user; ! // If Akismet connections are not enabled, we have nothing else to do here. ! if (!variable_get('akismet_connection_enabled', 1)) { ! return; } ! // Detect node edit/add form. ! if (preg_match('#^(.*)_node_form$#', $form_id, $matches)) { // @TODO: - return; } ! // Hook into comment edit/reply form. ! if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1)) { ! if (!user_access('administer comments')) { ! if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { ! // This is the simple hook method, we already have the $cid. ! $form['#submit']['_akismet_comment_form_submit'] = array(); } ! else { ! // This is a bit more complex, because the user is creating a new comment, so ! // how do we get the $cid? See comments below, within our own submit callback. ! $form['#submit'] = array('_akismet_comment_form_submit' => array($form['#submit'])); } } } --- 180,382 ---- /** ! * Implementation of hook_menu(). */ ! function akismet_menu($may_cache) { ! $items = array(); ! if (!$may_cache) { ! // Paths may look like 'akismet/content_type/content_id/operation' ! if (arg(0) == 'akismet' && is_numeric(arg(2))) { ! $content_type = arg(1); ! if ($content_type == 'node' || ($content_type == 'comment' && module_exist('comment'))) { ! $op = arg(3); ! if ($op == 'publish' || $op == 'unpublish') { ! $callback = 'akismet_switch_content_status'; ! else if ($op == 'submit-spam' || $op == 'submit-ham') { ! $callback = 'akismet_switch_spam_status'; ! } ! if (isset($callback) && akismet_content_exists($content_type, arg(2))) { ! $items[] = array('path' => 'akismet', 'title' => t('switch content status'), ! 'callback' => $callback, ! 'access' => ($content_type == 'node' ? user_access('administer nodes') : user_access('administer comments')), ! 'type' => MENU_CALLBACK); ! } ! } ! } ! } ! return $items; } /** ! * Implementation of hook_link(). */ ! function akismet_link($type, $content = 0, $main = 0) { ! $links = array(); ! if ($type == 'comment' && user_access('administer comments') && variable_get('akismet_comment_links_enabled', 1)) { ! if ($content->status == COMMENT_PUBLISHED) { ! $links[] = l(t('unpublish'), "akismet/comment/$content->cid/unpublish"); ! } ! else if ($content->status == COMMENT_NOT_PUBLISHED) { ! $links[] = l(t('publish'), "akismet/comment/$content->cid/publish"); ! } ! if (variable_get('akismet_connection_enabled', 1)) { ! if (akismet_content_is_spam('comment', $content->cid)) { ! $links[] = l(t('submit ham'), "akismet/comment/$content->cid/submit-ham"); ! } ! else { ! $links[] = l(t('submit spam'), "akismet/comment/$content->cid/submit-spam"); ! } ! } ! } ! else if ($type == 'node' && user_access('administer nodes') && variable_get('akismet_node_links_enabled', 0)) { ! if ($content->status) { ! $links[] = l(t('unpublish'), "akismet/node/$content->nid/unpublish"); ! } ! else { ! $links[] = l(t('publish'), "akismet/node/$content->nid/publish"); ! } ! if (variable_get('akismet_connection_enabled', 1)) { ! if (akismet_content_is_spam('node', $content->nid)) { ! $links[] = l(t('submit ham'), "akismet/node/$content->nid/submit-ham"); ! } ! else { ! $links[] = l(t('submit spam'), "akismet/node/$content->nid/submit-spam"); ! } ! } ! } ! return $links; ! } ! /** ! * Menu callback; publish/unpublish content. ! * ! * @param string Content type; it can be 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! * @param string Operation; it can be 'publish' or 'unpublish'. ! */ ! function akismet_switch_content_status($content_type, $op, $content_id) { ! if ($content_type == 'comment') { ! // Retrieve the comment (existence has been checked in hook_menu). ! $comment = akismet_content_load($content_type, $content_id); ! if ($op == 'publish' && $comment->status == COMMENT_NOT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'publish'); ! } ! else if ($op == 'unpublish' && $comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'unpublish'); ! } ! drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); ! } ! else if ($content_type == 'node') { ! // @TODO: } + drupal_not_found(); + } ! /** ! * Menu callback; mark/unmark content as spam. ! * ! * When content is marked as spam, it is also unpublished (if necessary) and vice-versa. ! * ! * @param string Content type; it can be 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! * @param string Operation; it can be 'submit-spam' or 'submit-ham'. ! */ ! function akismet_switch_spam_status($content_type, $op, $content_id) { ! $is_spam = akismet_content_is_spam($content_type, $content_id); ! if ($content_type == 'comment') { ! // Retrieve the comment (existence has been checked in hook_menu). ! $comment = akismet_content_load($content_type, $content_id); ! // insert or remove the spam marker (publishing/unpublishing if necessary). ! if ($op == 'submit-spam') { ! if (!$is_spam) { ! akismet_content_spam_operation($content_type, $content_id, 'submit-spam'); ! } ! if ($comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'unpublish'); ! } ! } ! else if ($op == 'submit-ham') { ! if ($is_spam) { ! akismet_content_spam_operation($content_type, $content_id, 'submit-ham'); ! } ! if ($comment->status == COMMENT_NOT_PUBLISHED) { ! akismet_content_publish_operation($content_type, $comment, 'publish'); ! } ! } ! drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); ! } ! else if ($content_type == 'node') { // @TODO: } + drupal_not_found(); + } ! /** ! * Implementation of hook_nodeapi(). ! */ ! function akismet_nodeapi(&$node, $op, $teaser, $page) { ! switch ($op) { ! case 'insert': ! case 'update': ! // If Akismet connections are not enabled, we have nothing else to do here. ! // Also quit asap, if current user has administration permission. ! if (!variable_get('akismet_connection_enabled', 1) || user_access('administer nodes')) { ! break; } ! ! // Now, check if it's about a node type that we have not been explicitly requested to check. ! $check_nodetypes = variable_get('akismet_check_nodetypes', NULL); ! if (is_array($check_nodetypes) && isset($check_nodetypes[$node->type]) && $check_nodetypes[$node->type]) { ! break; ! } ! ! // Ok, let's send a query to Akismet. ! if (akismet_api_cmd_comment_check(akismet_build_akismet_comment_data('node', $node))) { ! // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('node', $node->nid, 'submit-spam'); ! // Unpublish the node, if necessary. ! if ($node->status) { ! akismet_content_publish_operation('node', $node, 'unpublish'); ! } ! // Since users won't see their content published, show them a polite explanation on why. ! $content_type_name = node_get_name($node); ! drupal_set_message(t('Your %content-type-name has been queued for moderation by site administrators and will be published after approval.', array('%content-type-name' => $content_type_name))); ! // Add an entry to the watchdog log. ! watchdog('content', t('Spam detected by akismet in %content-type-name: %title', array('%content-type-name' => $content_type_name, '%title' => theme('placeholder', $node->title))), WATCHDOG_WARNING, l(t('view'), "node/$node->nid")); } + break; + case 'delete': + db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'node' AND content_id = %d", $node->nid); + break; + } + } + + /** + * Implementation of hook_comment(). + */ + function akismet_comment(&$comment, $op) { + if ($op == 'delete') { + db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = 'comment' AND content_id = %d", $content->cid); + } + } + + /** + * Implementation of hook_form_alter(). + */ + function akismet_form_alter($form_id, &$form) { + // If Akismet connections are not enabled, we have nothing else to do here. + if (!variable_get('akismet_connection_enabled', 1)) { + return; + } + + // Hook into comment edit/reply form. + if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1) && !user_access('administer comments')) { + if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { + // This is the simple hook method, we already have the $cid. + $form['#submit']['_akismet_comment_form_submit'] = array(); + } + else { + // This is a bit more complex, because the user is creating a new comment, so + // how do we get the $cid? See comments below, within our own submit callback. + $form['#submit'] = array('_akismet_comment_form_submit' => array($form['#submit'])); } } *************** *** 363,372 **** $goto = NULL; ! // If the comment id being edited there's no problem to get the $cid. // In this case, the original #submit callback has already been called. if (isset($form_values['cid'])) { $cid = $form_values['cid']; } ! // However, if the comment is being created we'll try to get the $cid from the // return value of the original #submit callback. It's an array that customizes // the URL the user should be sent when the form is submitted. It contains the --- 390,399 ---- $goto = NULL; ! // If the comment is being edited, then there's no problem to get the $cid. // In this case, the original #submit callback has already been called. if (isset($form_values['cid'])) { $cid = $form_values['cid']; } ! // However, if the comment is being created, we'll try to get the $cid from the // return value of the original #submit callback. It's an array that customizes // the URL the user should be sent when the form is submitted. It contains the *************** *** 394,410 **** // information that we need to make the Akismet request to check for spam. if ($cid) { ! $comment = _akismet_comment_load($cid, TRUE); // If we got a comment, send query to Akismet. ! if ($comment && akismet_api_cmd_comment_check($comment)) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_set_content_status('comment', $cid, AKISMET_CONTENT_STATUS_SPAM); // Unpublish the comment, if necessary. if ($comment->status == COMMENT_PUBLISHED) { ! akismet_comment_operation($cid, 'unpublish'); } // Since users won't see their replies published, show them a polite explanation on why. drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.')); // Add an entry to the watchdog log. ! watchdog('content', t('Comment spam, detected by akismet: %subject.', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); } } --- 421,437 ---- // information that we need to make the Akismet request to check for spam. if ($cid) { ! $comment = akismet_content_load('comment', $cid, TRUE); // If we got a comment, send query to Akismet. ! if ($comment && akismet_api_cmd_comment_check(akismet_build_akismet_comment_data('comment', $comment))) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('comment', $cid, 'submit-spam'); // Unpublish the comment, if necessary. if ($comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation('comment', $comment, 'unpublish'); } // Since users won't see their replies published, show them a polite explanation on why. drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.')); // Add an entry to the watchdog log. ! watchdog('content', t('Spam detected by akismet in comment: %subject', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); } } *************** *** 415,473 **** /** ! * Does a comment exist? * ! * @param int Comment ID. */ ! function _akismet_comment_exists($cid) { ! return db_result(db_query('SELECT 1 FROM {comments} WHERE cid = %d', $cid)); } /** ! * Load a comment. * ! * @param int Comment ID. ! * @param boolen Whether to load all possible comment data or not (optional, defaults to FALSE) */ ! function _akismet_comment_load($cid, $alldata = FALSE) { ! if ($alldata) { ! $comment = db_fetch_object(db_query(db_rewrite_sql('SELECT c.*, u.name AS registered_name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', 'c'), $cid)); ! if ($comment->uid) { ! $comment->name = $comment->registered_name; } } else { ! $comment = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $cid)); } ! return $comment; } /** ! * Wrapper for comment publish/unpublish operations. * ! * This function is based on comment.module::comment_admin_overview_submit() ! * so we might want to keep an eye there for future changes. */ ! function akismet_comment_operation($cid, $op) { ! static $operations = FALSE; ! // cached in case we need to come here more than once per request. ! if (!$operations) { ! $operations = comment_operations(); } - // extract the appropriate database query operation - $query = $operations[$op][1]; - // perform the update action, then refresh node statistics - db_query($query, $cid); - $comment = _comment_load($cid); - _comment_update_node_statistics($comment->nid); - // Allow modules to respond to the updating of a comment. - comment_invoke_comment($comment, $op); - // Add an entry to the watchdog log. - $action = ($op == 'unpublish' ? t('unpublished') : t('published')); - watchdog('content', t('Comment %action: %subject.', array('%action' => $action, '%subject' => theme('placeholder', $comment->subject))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $comment->nid, NULL, NULL, 'comment-'. $comment->cid)); } ! /****************************************\ Akismet API implementation ! \****************************************/ define('AKISMET_API_HOST', 'rest.akismet.com'); --- 442,627 ---- /** ! * Check if specified content is marked as spam. * ! * @param string Content type; can be either 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! * @return boolean TRUE if spam, FALSE otherwise. */ ! function akismet_content_is_spam($content_type, $content_id) { ! return db_result(db_query("SELECT 1 FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id)); } /** ! * Check if specified content exists. * ! * @param string Content type; can be either 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! * @return boolean TRUE if content exists; FALSE otherwise. */ ! function akismet_content_exists($content_type, $content_id) { ! if ($content_type == 'node') { ! return db_result(db_query('SELECT 1 FROM {node} WHERE nid = %d', $content_id)); ! } ! if ($content_type == 'comment') { ! return db_result(db_query('SELECT 1 FROM {comments} WHERE cid = %d', $content_id)); ! } ! return FALSE; ! } ! ! /** ! * Load a node or a comment. ! * ! * @param string Content type; can be either 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! * @param boolen Whether to load all possible comment data or only the basic record (optional, defaults to FALSE). ! * @return mixed An object with requested content or FALSE on failure. ! */ ! function akismet_content_load($content_type, $content_id, $alldata = FALSE) { ! if ($content_type == 'node') { ! if ($alldata) { ! $content = node_load($content_id); ! if (empty($content->nid)) { ! $content = FALSE; ! } ! } ! else { ! $content = db_fetch_object(db_query('SELECT * FROM {node} WHERE nid = %d', $content_id)); ! } ! } ! else if ($content_type == 'comment') { ! if ($alldata) { ! $content = db_fetch_object(db_query(db_rewrite_sql('SELECT c.*, u.name AS registered_name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', 'c'), $content_id)); ! if ($content->uid) { ! $content->name = $content->registered_name; ! } ! } ! else { ! $content = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $content_id)); } } else { ! $content = FALSE; } ! return $content; } /** ! * Mark content as spam or remove the mark. * ! * A previous check needs to be made in order to see if content is already marked as spam or not. ! * ! * @param string Content type; can be either 'node' or 'comment'. ! * @param integer Content ID; can be either a nid or a cid. ! * @param string Operation; it can be 'submit-spam' or 'submit-ham'. */ ! function akismet_content_spam_operation($content_type, $content_id, $op) { ! if ($op == 'spam') { ! db_query("INSERT INTO {akismet_spam_marks} (content_type, content_id, spam_created) VALUES ('%s', %d, %d)", $content_type, $content_id, time()); ! if (variable_get('akismet_connection_enabled', 1)) { ! // @TODO: Submit spam!? ! } ! } ! else if ($op == 'ham') { ! db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id); ! if (variable_get('akismet_connection_enabled', 1)) { ! // @TODO: Submit ham!? ! } } } ! /** ! * Execute content publish/unpublish operations. ! * ! * @param string Content type; it can be 'node' or 'comment'. ! * @param object Content object. ! * @param string Operation; it can be 'publish' or 'unpublish'. ! */ ! function akismet_content_publish_operation($content_type, $content, $op) { ! if ($content_type == 'node') { ! // This code snippet is based on node.module::node_admin_nodes_submit() ! // Only the node record is updated, no other hooks are invoked. ! ! // Cache operations in case we need to come here more than once per request. ! static $node_operations = FALSE; ! if (!$node_operations) { ! $node_operations = node_operations(); ! } ! ! // extract the appropriate database query operation ! $query = $node_operations[$op][1]; ! // perform the update action, then refresh node statistics ! db_query($query, $content->nid); ! ! // Add an entry to the watchdog log. ! $action = ($op == 'unpublish' ? t('unpublished') : t('published')); ! watchdog('content', t('Content %action: %title', array('%action' => $action, '%subject' => theme('placeholder', $content->title))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $comment->nid)); ! } ! else if ($content_type == 'comment') { ! // This code snippet is based on comment.module::comment_admin_overview_submit() ! ! // Cache operations in case we need to come here more than once per request. ! static $comment_operations = FALSE; ! if (!$comment_operations) { ! $comment_operations = comment_operations(); ! } ! ! // extract the appropriate database query operation ! $query = $comment_operations[$op][1]; ! // perform the update action, then refresh node statistics ! db_query($query, $content->cid); ! ! // Update comment statistics. ! _comment_update_node_statistics($content->nid); ! // Allow modules to respond to the updating of a comment. ! comment_invoke_comment($content, $op); ! ! // Add an entry to the watchdog log. ! $action = ($op == 'unpublish' ? t('unpublished') : t('published')); ! watchdog('content', t('Comment %action: %subject', array('%action' => $action, '%subject' => theme('placeholder', $content->subject))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $content->nid, NULL, NULL, 'comment-'. $content->cid)); ! } ! } ! ! /** ! * Prepare comment data for Akismet requests. ! * ! * @param string 'node' or 'comment' ! * @param object $node or $comment ! * @return array ! */ ! function akismet_build_akismet_comment_data($content_type, $content) { ! // Prepare data that is common to nodes/comments. ! $comment_data = array( ! // IP address of the comment submitter. ! 'user_ip' => (!empty($content->hostname) ? $content->hostname : $_SERVER['REMOTE_ADDR']), ! // User agent information of the comment submitter. ! 'user_agent' => $_SERVER['HTTP_USER_AGENT'], ! // The content of the HTTP_REFERER header should be sent here. ! 'referrer' => $_SERVER['HTTP_REFERER'], ! // May be blank, comment, trackback, pingback, or a made up value like "registration". ! 'comment_type' => '', ! // Submitted name with the comment. ! 'comment_author' => $content->name, ! ); ! ! // Prepare data that varies depending on type of content. ! if ($content_type == 'comment') { ! $comment_data['permalink'] = url("node/$content->nid", NULL, "comment-$content->cid", TRUE); ! $comment_data['comment_author_email'] = $content->mail; ! $comment_data['comment_author_url'] = $content->homepage; ! $comment_data['comment_content'] = $content->comment; ! } ! else { ! global $user; ! $comment_data['permalink'] = url("node/$content->nid"); ! $comment_data['comment_author_email'] = $user->mail; ! $comment_data['comment_author_url'] = ''; ! $comment_data['comment_content'] = $content->body; ! } ! return $comment_data; ! } ! ! /************************************************************\ Akismet API implementation ! \************************************************************/ define('AKISMET_API_HOST', 'rest.akismet.com'); *************** *** 479,484 **** * Akismet API: Key Verification rest.akismet.com/1.1/verify key * ! * @return boolean ! * Returns TRUE if API key is valid. */ function akismet_api_cmd_verify_key($key) { --- 633,638 ---- * Akismet API: Key Verification rest.akismet.com/1.1/verify key * ! * @param string WordPress API Key. ! * @return boolean TRUE if API key is valid; FALSE otherwise. */ function akismet_api_cmd_verify_key($key) { *************** *** 492,503 **** * Akismet API: Comment Check api-key.rest.akismet.com/1.1/comment-check * ! * @param object $comment ! * ! * @return boolean ! * Returns TRUE if the comment IS spam. */ ! function akismet_api_cmd_comment_check($comment) { ! $request_data = array_merge(_akismet_api_build_server_data(), _akismet_api_build_comment_data($comment)); ! $query_string = _akismet_api_get_query_string($request_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); --- 646,655 ---- * Akismet API: Comment Check api-key.rest.akismet.com/1.1/comment-check * ! * @param array Comment data; see function akismet_build_akismet_comment_data(). ! * @return boolean TRUE if the comment IS spam; FALSE otherwise. */ ! function akismet_api_cmd_comment_check($comment_data) { ! $comment_data = array_merge(_akismet_api_build_server_data(), $comment_data); ! $query_string = _akismet_api_get_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); *************** *** 508,516 **** * Akismet API: Submit Spam api-key.rest.akismet.com/1.1/submit-spam * ! * @param object $comment */ ! function akismet_api_cmd_submit_spam($comment) { ! $request_data = _akismet_api_build_comment_data($comment); ! $query_string = _akismet_api_get_query_string($request_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-spam'); --- 660,667 ---- * Akismet API: Submit Spam api-key.rest.akismet.com/1.1/submit-spam * ! * @param array Comment data; see function akismet_build_akismet_comment_data(). */ ! function akismet_api_cmd_submit_spam($comment_data) { ! $query_string = _akismet_api_get_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-spam'); *************** *** 520,528 **** * Akismet API: Submit Ham api-key.rest.akismet.com/1.1/submit-ham * ! * @param object $comment */ ! function akismet_api_cmd_submit_ham($comment) { ! $request_data = _akismet_api_build_comment_data($comment); ! $query_string = _akismet_api_get_query_string($request_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-ham'); --- 671,678 ---- * Akismet API: Submit Ham api-key.rest.akismet.com/1.1/submit-ham * ! * @param array Comment data; see function akismet_build_akismet_comment_data(). */ ! function akismet_api_cmd_submit_ham($comment_data) { ! $query_string = _akismet_api_get_query_string($comment_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-ham'); *************** *** 530,568 **** /** - * Prepare comment data that is to be sent along akismet requests. - * - * @param object $comment - * - * @return array - */ - function _akismet_api_build_comment_data($comment) { - $comment_keys = array( - // IP address of the comment submitter. - 'user_ip' => (!empty($comment->hostname) ? $comment->hostname : $_SERVER['REMOTE_ADDR']), - // User agent information of the comment submitter. - 'user_agent' => $_SERVER['HTTP_USER_AGENT'], - // The content of the HTTP_REFERER header should be sent here. - 'referrer' => $_SERVER['HTTP_REFERER'], - // The permanent location of the entry the comment was submitted to. - 'permalink' => url("node/$comment->nid", NULL, "comment-$comment->cid", TRUE), - // May be blank, comment, trackback, pingback, or a made up value like "registration". - 'comment_type' => '', - // Submitted name with the comment. - 'comment_author' => $comment->name, - // Submitted email address. - 'comment_author_email' => $comment->mail, - // Commenter URL. - 'comment_author_url' => $comment->homepage, - // The content that was submitted. - 'comment_content' => $comment->comment - ); - $comment_data = array(); - foreach ($comment_keys as $key => $value) { - $comment_data[$key] = $value; - } - return $comment_data; - } - - /** * Prepare $_SERVER data that is to be sent along akismet requests. * --- 680,683 ---- *************** *** 608,615 **** /** ! * Convert an associative array into a string formatted according to akismet rules. * * @param array - * * @return string */ --- 723,729 ---- /** ! * Convert an associative array into a query string formatted according to akismet rules. * * @param array * @return string */ *************** *** 626,638 **** * Perform a HTTP POST request against the akismet server. * ! * @param string $request ! * The request. ! * @param string $host ! * The akismet host, prefixed with the API key (except when checking for the key itself). ! * @param string $path ! * The path where to perform the request. ! * ! * @return array ! * Headers in $response[0] and entity in $response[1] */ function _akismet_api_http_post($request, $host, $path) { --- 740,747 ---- * Perform a HTTP POST request against the akismet server. * ! * @param string The request. ! * @param string The akismet host, prefixed with the API key (except when checking for the key itself). ! * @param string The path where to perform the request. ! * @return array Headers in $response[0] and entity in $response[1]. */ function _akismet_api_http_post($request, $host, $path) { |
From: <php...@li...> - 2006-06-06 00:56:09
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6858 Modified Files: akismet.module Log Message: - Implemented spam counter (settings and counter, a themable block is on the works). - TODO notes updated. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** akismet.module 5 Jun 2006 13:32:39 -0000 1.4 --- akismet.module 5 Jun 2006 15:37:15 -0000 1.5 *************** *** 5,11 **** WARNING: Module is in development! @TODO: Think about and implement spam moderation queue. @TODO: Review the help page. - @TODO: Implement spam counter (and maybe a themable block?). @TODO: Implement an opt-in option for administrators to e-mail them when content is posted (maybe for all posts, or for detected spam or nothing). --- 5,11 ---- WARNING: Module is in development! + @TODO: Implement a themable block (or something for spam counter). @TODO: Think about and implement spam moderation queue. @TODO: Review the help page. @TODO: Implement an opt-in option for administrators to e-mail them when content is posted (maybe for all posts, or for detected spam or nothing). *************** *** 228,231 **** --- 228,265 ---- } + $date_formats = array( + 'F j, Y', 'j F, Y', 'Y, F j', + 'M j, Y', 'j M, Y', 'Y, M j', + 'Y/m/d', 'm/d/Y', 'd/m/Y', + 'Y-m-d', 'm-d-Y', 'd-m-Y' + ); + $date_options = array(); + $now = time(); + foreach ($date_formats as $format) { + $date_options[$format] = format_date($now, 'custom', $format); + } + + $form['counter_options'] = array( + '#type' => 'fieldset', '#title' => t('Counter options'), + '#collapsible' => TRUE, '#collapsed' => TRUE + ); + $form['counter_options']['akismet_counter_spam'] = array( + '#type' => 'textfield', '#title' => t('Spam counter'), + '#default_value' => variable_get('akismet_counter_spam', 0), + '#size' => 10, '#maxlength' => 10, + '#description' => t('This counter is incremented for every spam caught by Akismet.') + ); + $form['counter_options']['akismet_counter_since'] = array( + '#type' => 'date', '#title' => t('Counting since'), + '#default_value' => variable_get('akismet_counter_since', array('day' => date('j'), 'month' => date('n'), 'year' => date('Y'))), + '#description' => t('This is the date that will tell your visitor when your Akismet spam counter started to increment.') + ); + $form['counter_options']['akismet_counter_date_format'] = array( + '#type' => 'select', '#title' => t('Date format'), + '#default_value' => variable_get('akismet_counter_date_format', $date_formats[0]), + '#options' => $date_options, + '#description' => t('Date format used to render the <em>Counting since</em> date.') + ); + return $form; } *************** *** 414,417 **** --- 448,453 ---- // Oops! Akismet is telling us we got spammed, let's mark the comment as such. akismet_content_spam_operation('node', $node, 'submit-spam'); + // Increment Akismet spam counter + variable_set('akismet_counter_spam', intval(variable_get('akismet_counter_spam', 0)) + 1); } *************** *** 520,523 **** --- 556,561 ---- // Oops! Akismet is telling us we got spammed, let's mark the comment as such. akismet_content_spam_operation('comment', $comment, 'submit-spam'); + // Increment Akismet spam counter + variable_set('akismet_counter_spam', intval(variable_get('akismet_counter_spam', 0)) + 1); } |
From: <php...@li...> - 2006-06-06 00:08:41
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31202 Modified Files: akismet.module Log Message: - Fixed bug is Akismet connection code. - Normalized return codes for particular implementation of the Akismet API. - Added ability to set connection timeout in the settings panel. - Reviewed usage of watchdog to remove redundant messages. Index: akismet.module =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/akismet.module,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** akismet.module 5 Jun 2006 15:37:15 -0000 1.5 --- akismet.module 6 Jun 2006 00:08:35 -0000 1.6 *************** *** 20,26 **** define('AKISMET_API_VERSION', '1.1'); define('AKISMET_USERAGENT', 'Drupal/4.7 | akismet.module/1.0'); define('AKISMET_API_RESULT_IS_SPAM', 1); define('AKISMET_API_RESULT_IS_HAM', 2); - define('AKISMET_API_RESULT_ERROR', -1); --- 20,27 ---- define('AKISMET_API_VERSION', '1.1'); define('AKISMET_USERAGENT', 'Drupal/4.7 | akismet.module/1.0'); + define('AKISMET_API_RESULT_ERROR', -1); + define('AKISMET_API_RESULT_SUCCESS', 0); define('AKISMET_API_RESULT_IS_SPAM', 1); define('AKISMET_API_RESULT_IS_HAM', 2); *************** *** 99,104 **** } else { ! $is_valid = akismet_api_cmd_verify_key($akismet_wpapikey); ! $akismet_collapsed = $is_valid; } if ($akismet_collapsed) { --- 100,104 ---- } else { ! $akismet_collapsed = $is_valid = (akismet_api_cmd_verify_key($akismet_wpapikey) == AKISMET_API_RESULT_SUCCESS ? TRUE : FALSE); } if ($akismet_collapsed) { *************** *** 136,139 **** --- 136,149 ---- )) ); + $timeout_options = array(); + for ($n = 1; $n <= 30; $n++) { + $timeout_options[$n] = $n; + } + $form['general']['akismet_connection_timeout'] = array( + '#type' => 'select', '#title' => t('Connection timeout'), + '#default_value' => variable_get('akismet_connection_timeout', 10), + '#options' => $timeout_options, + '#description' => t('This option allows you to specify the connection timeout in seconds that is used for real time Akismet connections.') + ); $interval_options = drupal_map_assoc(array(0, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval'); $interval_options[0] = t('never'); *************** *** 447,451 **** if ($akismet_api_result == AKISMET_API_RESULT_IS_SPAM) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('node', $node, 'submit-spam'); // Increment Akismet spam counter variable_set('akismet_counter_spam', intval(variable_get('akismet_counter_spam', 0)) + 1); --- 457,461 ---- if ($akismet_api_result == AKISMET_API_RESULT_IS_SPAM) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('node', $node, 'submit-spam', FALSE); // Increment Akismet spam counter variable_set('akismet_counter_spam', intval(variable_get('akismet_counter_spam', 0)) + 1); *************** *** 454,458 **** // Unpublish the node, if necessary. if ($node->status) { ! akismet_content_publish_operation('node', $node, 'unpublish'); } --- 464,468 ---- // Unpublish the node, if necessary. if ($node->status) { ! akismet_content_publish_operation('node', $node, 'unpublish', FALSE); } *************** *** 555,559 **** if ($akismet_api_result == AKISMET_API_RESULT_IS_SPAM) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('comment', $comment, 'submit-spam'); // Increment Akismet spam counter variable_set('akismet_counter_spam', intval(variable_get('akismet_counter_spam', 0)) + 1); --- 565,569 ---- if ($akismet_api_result == AKISMET_API_RESULT_IS_SPAM) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. ! akismet_content_spam_operation('comment', $comment, 'submit-spam', FALSE); // Increment Akismet spam counter variable_set('akismet_counter_spam', intval(variable_get('akismet_counter_spam', 0)) + 1); *************** *** 562,566 **** // Unpublish the comment, if necessary. if ($comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation('comment', $comment, 'unpublish'); } --- 572,576 ---- // Unpublish the comment, if necessary. if ($comment->status == COMMENT_PUBLISHED) { ! akismet_content_publish_operation('comment', $comment, 'unpublish', FALSE); } *************** *** 643,648 **** * @param object Content object. * @param string Operation; it can be 'submit-spam' or 'submit-ham'. */ ! function akismet_content_spam_operation($content_type, $content, $op) { if ($content_type == 'node') { $content_id = $content->nid; --- 653,659 ---- * @param object Content object. * @param string Operation; it can be 'submit-spam' or 'submit-ham'. + * @param boolean TRUE to log action (default); FALSE otherwise (ie. the caller logs the action). */ ! function akismet_content_spam_operation($content_type, $content, $op, $log_action = TRUE) { if ($content_type == 'node') { $content_id = $content->nid; *************** *** 679,684 **** } ! // Add an entry to the watchdog log. ! watchdog('content', t('%action: %title', array('%action' => $action, '%title' => theme('placeholder', $content_title))), WATCHDOG_NOTICE, $content_link); } --- 690,696 ---- } ! if ($log_action) { ! watchdog('content', t('%action: %title', array('%action' => $action, '%title' => theme('placeholder', $content_title))), WATCHDOG_NOTICE, $content_link); ! } } *************** *** 689,704 **** * @param object Content object. * @param string Operation; it can be 'publish' or 'unpublish'. */ ! function akismet_content_publish_operation($content_type, $content, $op) { if ($content_type == 'node') { // This code snippet is based on node.module::node_admin_nodes_submit() // Only the node record is updated, no other hooks are invoked. ! // perform the update action, then refresh node statistics db_query('UPDATE {node} SET status = %d WHERE nid = %d', ($op == 'publish' ? 1 : 0), $content->nid); ! // Add an entry to the watchdog log. ! $action = ($op == 'publish' ? t('Content published') : t('Content unpublished')); ! watchdog('content', t('%action: %title', array('%action' => $action, '%title' => theme('placeholder', $content->title))), WATCHDOG_NOTICE, l(t('view'), "node/$content->nid")); } else if ($content_type == 'comment') { --- 701,718 ---- * @param object Content object. * @param string Operation; it can be 'publish' or 'unpublish'. + * @param boolean TRUE to log action (default); FALSE otherwise (ie. the caller logs the action). */ ! function akismet_content_publish_operation($content_type, $content, $op, $log_action = TRUE) { if ($content_type == 'node') { // This code snippet is based on node.module::node_admin_nodes_submit() // Only the node record is updated, no other hooks are invoked. ! // perform the update action. db_query('UPDATE {node} SET status = %d WHERE nid = %d', ($op == 'publish' ? 1 : 0), $content->nid); ! if ($log_action) { ! $action = ($op == 'publish' ? t('Content published') : t('Content unpublished')); ! watchdog('content', t('%action: %title', array('%action' => $action, '%title' => theme('placeholder', $content->title))), WATCHDOG_NOTICE, l(t('view'), "node/$content->nid")); ! } } else if ($content_type == 'comment') { *************** *** 711,717 **** } ! // extract the appropriate database query operation $query = $comment_operations[$op][1]; ! // perform the update action, then refresh node statistics db_query($query, $content->cid); --- 725,731 ---- } ! // extract the appropriate database query operation. $query = $comment_operations[$op][1]; ! // perform the update action, then refresh node statistics. db_query($query, $content->cid); *************** *** 721,727 **** comment_invoke_comment($content, $op); ! // Add an entry to the watchdog log. ! $action = ($op == 'publish' ? t('Comment published') : t('Comment unpublished')); ! watchdog('content', t('%action: %subject', array('%action' => $action, '%subject' => theme('placeholder', $content->subject))), WATCHDOG_NOTICE, l(t('view'), "node/$content->nid", NULL, NULL, "comment-$content->cid")); } } --- 735,742 ---- comment_invoke_comment($content, $op); ! if ($log_action) { ! $action = ($op == 'publish' ? t('Comment published') : t('Comment unpublished')); ! watchdog('content', t('%action: %subject', array('%action' => $action, '%subject' => theme('placeholder', $content->subject))), WATCHDOG_NOTICE, l(t('view'), "node/$content->nid", NULL, NULL, "comment-$content->cid")); ! } } } *************** *** 774,784 **** * * @param string WordPress API Key. ! * @return boolean TRUE if API key is valid; FALSE otherwise. */ function akismet_api_cmd_verify_key($key) { global $base_url; ! $request = "key=$key&blog=$base_url"; ! $response = _akismet_api_http_post($request, AKISMET_API_HOST, '/'. AKISMET_API_VERSION .'/verify-key'); ! return ('valid' == $response[1] ? TRUE : FALSE); } --- 789,801 ---- * * @param string WordPress API Key. ! * @return integer See constants AKISMET_API_RESULT_xxx. */ function akismet_api_cmd_verify_key($key) { global $base_url; ! if (!empty($key)) { ! $request = "key=$key&blog=$base_url". base_path(); ! $response = _akismet_api_http_post($request, AKISMET_API_HOST, '/'. AKISMET_API_VERSION .'/verify-key'); ! } ! return (isset($response[1]) && 'valid' == $response[1] ? AKISMET_API_RESULT_SUCCESS : AKISMET_API_RESULT_ERROR); } *************** *** 791,807 **** function akismet_api_cmd_comment_check($comment_data) { if (!variable_get('akismet_connection_enabled', 1)) { ! return FALSE; } ! $comment_data = array_merge(_akismet_api_prepare_request_data(), $comment_data); ! $query_string = _akismet_api_build_query_string($comment_data); ! $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; ! $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); ! if ('true' == $response[1]) { ! return AKISMET_API_RESULT_IS_SPAM; } ! if ('false' == $response[1]) { ! return AKISMET_API_RESULT_IS_HAM; } ! return AKISMET_API_RESULT_ERROR; } --- 808,824 ---- function akismet_api_cmd_comment_check($comment_data) { if (!variable_get('akismet_connection_enabled', 1)) { ! return AKISMET_API_RESULT_ERROR; } ! $akismet_wpapikey = variable_get('akismet_wpapikey', ''); ! if (!empty($akismet_wpapikey)) { ! $comment_data = array_merge(_akismet_api_prepare_request_data(), $comment_data); ! $query_string = _akismet_api_build_query_string($comment_data); ! $host = $akismet_wpapikey .'.'. AKISMET_API_HOST; ! $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); } ! if (!isset($response[1])) { ! return AKISMET_API_RESULT_ERROR; } ! return ('true' == $response[1] ? AKISMET_API_RESULT_IS_SPAM : AKISMET_API_RESULT_IS_HAM); } *************** *** 810,821 **** * * @param array Comment data; see function akismet_prepare_comment_data(). */ function akismet_api_cmd_submit_spam($comment_data) { if (!variable_get('akismet_connection_enabled', 1)) { ! return; } ! $query_string = _akismet_api_build_query_string($comment_data); ! $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; ! $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-spam'); } --- 827,843 ---- * * @param array Comment data; see function akismet_prepare_comment_data(). + * @return integer See constants AKISMET_API_RESULT_xxx. */ function akismet_api_cmd_submit_spam($comment_data) { if (!variable_get('akismet_connection_enabled', 1)) { ! return AKISMET_API_RESULT_ERROR; } ! $akismet_wpapikey = variable_get('akismet_wpapikey', ''); ! if (!empty($akismet_wpapikey)) { ! $query_string = _akismet_api_build_query_string($comment_data); ! $host = $akismet_wpapikey .'.'. AKISMET_API_HOST; ! $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-spam'); ! } ! return (isset($response[1]) ? AKISMET_API_RESULT_SUCCESS : AKISMET_API_RESULT_ERROR); } *************** *** 824,835 **** * * @param array Comment data; see function akismet_prepare_comment_data(). */ function akismet_api_cmd_submit_ham($comment_data) { if (!variable_get('akismet_connection_enabled', 1)) { ! return; } ! $query_string = _akismet_api_build_query_string($comment_data); ! $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; ! $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-ham'); } --- 846,862 ---- * * @param array Comment data; see function akismet_prepare_comment_data(). + * @return integer See constants AKISMET_API_RESULT_xxx. */ function akismet_api_cmd_submit_ham($comment_data) { if (!variable_get('akismet_connection_enabled', 1)) { ! return AKISMET_API_RESULT_ERROR; } ! $akismet_wpapikey = variable_get('akismet_wpapikey', ''); ! if (!empty($akismet_wpapikey)) { ! $query_string = _akismet_api_build_query_string($comment_data); ! $host = $akismet_wpapikey .'.'. AKISMET_API_HOST; ! $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-ham'); ! } ! return (isset($response[1]) ? AKISMET_API_RESULT_SUCCESS : AKISMET_API_RESULT_ERROR); } *************** *** 901,905 **** */ function _akismet_api_http_post($request, $host, $path) { ! $fsock_timeout = 3; $http_request = "POST $path HTTP/1.0\r\n" --- 928,932 ---- */ function _akismet_api_http_post($request, $host, $path) { ! $fsock_timeout = (int)variable_get('akismet_connection_timeout', 10); $http_request = "POST $path HTTP/1.0\r\n" |
From: <php...@li...> - 2006-06-04 01:02:04
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30951 Modified Files: INSTALL.txt README.txt Log Message: Fixing in-dev warning. Index: INSTALL.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/INSTALL.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** INSTALL.txt 4 Jun 2006 00:52:45 -0000 1.1 --- INSTALL.txt 4 Jun 2006 01:01:54 -0000 1.2 *************** *** 11,15 **** WARNING: ! This module doesn not work, yet. It is still under development !!! --- 11,15 ---- WARNING: ! This module is still under development !!! Index: README.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/akismet/README.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README.txt 4 Jun 2006 00:52:45 -0000 1.1 --- README.txt 4 Jun 2006 01:01:54 -0000 1.2 *************** *** 11,15 **** WARNING: ! This module doesn not work, yet. It is still under development !!! --- 11,15 ---- WARNING: ! This module is still under development !!! |
From: <php...@li...> - 2006-06-04 00:52:56
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26662 Added Files: INSTALL.txt README.txt akismet.install akismet.module Log Message: Initial import. --- NEW FILE: README.txt --- $Id: README.txt,v 1.1 2006/06/04 00:52:45 markus_petrux Exp $ ******************************************************************** D R U P A L M O D U L E ******************************************************************** Name : akismet Version : 0.0.1 Author : markus_petrux [ http://www.phpmix.org ] Drupal : 4.7 ******************************************************************** WARNING: This module doesn not work, yet. It is still under development !!! ******************************************************************** DESCRIPTION: This module allows you to use Akismet services as an attempt to protect your site from being spammed. To use the akismet service, you need a WordPress.com API key. To get one, you have to sign up for a free account at wordpress.com Please, see the following pages for further information: http://akismet.com http://akismet.com/faq/ http://wordpress.com/api-keys/ ******************************************************************** INSTALLATION: Please, see the file INSTALL.txt in this directory. ******************************************************************** --- NEW FILE: INSTALL.txt --- $Id: INSTALL.txt,v 1.1 2006/06/04 00:52:45 markus_petrux Exp $ ******************************************************************** D R U P A L M O D U L E ******************************************************************** Name : akismet Version : 0.0.1 Author : markus_petrux [ http://www.phpmix.org ] Drupal : 4.7 ******************************************************************** WARNING: This module doesn not work, yet. It is still under development !!! ******************************************************************** INSTALLATION: 1. Create the folder 'modules/akismet' 2. Copy all modules files, keeping directory structure, to the folder 'modules/akismet' 3. Enable the akismet module in 'admin/modules' 4. You're done. ******************************************************************** Please, see the file README.txt for further information. --- NEW FILE: akismet.install --- <?php // $Id: akismet.install,v 1.1 2006/06/04 00:52:45 markus_petrux Exp $ /** * Implementation of hook_install(). */ function akismet_install() { switch ($GLOBALS['db_type']) { case 'mysql': case 'mysqli': db_query("CREATE TABLE {akismet_spam_marks} ( content_type varchar(20) NOT NULL default '', content_id int(10) unsigned NOT NULL default 0, spam_created int(11) unsigned NOT NULL default 0, UNIQUE content (content_type, content_id), INDEX spam_created (spam_created) ) /*!40100 DEFAULT CHARACTER SET utf8 */;"); break; case 'pgsql': db_query("CREATE TABLE {akismet_spam_marks} ( content_type varchar(20) NOT NULL default '', content_id integer NOT NULL default 0, spam_created integer NOT NULL default 0, CHECK (content_id>=0), CHECK (spam_created>=0) )"); db_query("CREATE UNIQUE INDEX {akismet_spam_marks_content} ON {akismet_spam_marks} (content_type, content_id)"); db_query("CREATE INDEX {akismet_spam_marks_spamcreated} ON {akismet_spam_marks} (spam_created)"); break; } } --- NEW FILE: akismet.module --- <?php // $Id: akismet.module,v 1.1 2006/06/04 00:52:45 markus_petrux Exp $ define('AKISMET_CONTENT_STATUS_SPAM', 1); define('AKISMET_CONTENT_STATUS_HAM' , 2); /** * Implementation of hook_help(). */ function akismet_help($section) { switch ($section) { case 'admin/modules#description': $output = t('Use <a href="%akismet">Akismet Service</a> to protect your site from being spammed.', array('%akismet' => 'http://akismet.com')); break; case 'admin/help/akismet': $output = t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', '%drupal' => 'http://drupal.org', '%akismet' => 'http://akismet.com' )); break; case 'admin/help#akismet': $output = t('<p>In order to use the <a href="%akismet">Akismet Service</a>, you need a <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.</p> <p>The <em>akismet module</em> can be <a href="%akismet-settings">configured</a> to automatically check for spam posted in content (nodes and/or comments). You can use <a href="%access-control">access control</a> to grant the <em>%no-check-perm</em> permission to <em>user roles</em> of your choice.</p> <p>Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. There is <a href="%akismet-settings">an option</a> that allows you to specify how long this information will be kept in the database. <em>Spam</em> older than a specified interval will be automatically removed. Requires crontab.</p> <p>Automatic spam detection can be enabled or disabled by content type and/or comments. In addition to this, the <em>akismet module</em> makes it easy for <em>content administrators</em> to manually <em>publish</em>/<em>unpublish</em> content and <em>mark</em>/<em>unmark</em> content as spam, from links available at the bottom of content.</p> <p></p>', array( '%akismet' => 'http://akismet.com', '%wpapikey' => 'http://wordpress.com/api-keys/', '%wordpress-com' => 'http://wordpress.com', '%akismet-faq' => 'http://akismet.com/faq/', '%akismet-settings' => url('admin/settings/akismet'), '%access-control' => url('admin/access'), '%no-check-perm' => t('post with no akismet checking') )); break; case 'admin/settings/akismet': $output = t('<p>The <a href="%akismet-module-home">akismet module</a> for <a href="%drupal">Drupal</a> allows you to use the <a href="%akismet">Akismet Service</a> to protect your site from being spammed.</p> <p>This panel allows you to configure all <em>akismet module</em> options. Please, refer to the <a href="%help-page">help page</a> for further information.</p>', array( '%akismet-module-home' => 'http://www.phpmix.org/projects/drupal', '%drupal' => 'http://drupal.org', '%akismet' => 'http://akismet.com', '%help-page' => url('admin/help/akismet') )); break; } return $output; } /** * Implementation of hook_perm(). */ function akismet_perm() { return array('post with no akismet checking'); } /** * Implementation of hook_menu(). */ function akismet_menu($may_cache) { $items = array(); if (!$may_cache) { // Paths may look like 'akismet/content_type/operation/content_id' if (arg(0) == 'akismet' && is_numeric(arg(3))) { $content_type = arg(1); if ($content_type == 'comment' && module_exist('comment')) { $op = arg(2); if ($op == 'publish' || $op == 'unpublish') { if (_akismet_comment_exists(arg(3))) { $items[] = array('path' => 'akismet', 'title' => t('switch comment status'), 'callback' => 'akismet_switch_content_status', 'access' => user_access('administer comments'), 'type' => MENU_CALLBACK); } } else if ($op == 'submit-spam' || $op == 'submit-ham') { if (_akismet_comment_exists(arg(3))) { $items[] = array('path' => 'akismet', 'title' => t('switch spam status'), 'callback' => 'akismet_switch_spam_status', 'access' => user_access('administer comments'), 'type' => MENU_CALLBACK); } } } else if ($content_type == 'node') { // @TODO: } } } return $items; } /** * Implementation of hook_link(). */ function akismet_link($type, $content = 0, $main = 0) { $links = array(); if ($type == 'comment' && user_access('administer comments') && variable_get('akismet_comment_links_enabled', 1)) { if ($content->status == COMMENT_PUBLISHED) { $links[] = l(t('unpublish'), "akismet/comment/unpublish/$content->cid"); } else if ($content->status == COMMENT_NOT_PUBLISHED) { $links[] = l(t('publish'), "akismet/comment/publish/$content->cid"); } if (variable_get('akismet_connection_enabled', 1)) { } if (akismet_is_content_spam('comment', $content->cid)) { $links[] = l(t('submit ham'), "akismet/comment/submit-ham/$content->cid"); } else { $links[] = l(t('submit spam'), "akismet/comment/submit-spam/$content->cid"); } } else if ($type == 'node' && user_access('administer nodes') && variable_get('akismet_node_links_enabled', 0)) { // @TODO: Implement node links ...et al. } return $links; } /** * Menu callback; publish/unpublish content. */ function akismet_switch_content_status($content_type, $op, $content_id) { if ($content_type == 'comment') { // Retrieve the comment (existence has been checked in hook_menu). $comment = _akismet_comment_load($content_id); if ($op == 'publish' && $comment->status == COMMENT_NOT_PUBLISHED) { akismet_comment_operation($content_id, 'publish'); } else if ($op == 'unpublish' && $comment->status == COMMENT_PUBLISHED) { akismet_comment_operation($content_id, 'unpublish'); } drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); } else if ($content_type == 'node') { // @TODO: } drupal_not_found(); } /** * Menu callback; mark/unmark content as spam. * * When content is marked as spam, it is also unpublished (if necessary) and vice-versa. */ function akismet_switch_spam_status($content_type, $op, $content_id) { $is_spam = akismet_is_content_spam($content_type, $content_id); if ($content_type == 'comment') { // Retrieve the comment (existence has been checked in hook_menu). $comment = _akismet_comment_load($content_id); // insert or remove the spam marker (publishing/unpublishing if necessary). if ($op == 'submit-spam') { if (!$is_spam) { akismet_set_content_status($content_type, $content_id, AKISMET_CONTENT_STATUS_SPAM); } if ($comment->status == COMMENT_PUBLISHED) { akismet_comment_operation($content_id, 'unpublish'); } } else if ($op == 'submit-ham') { if ($is_spam) { akismet_set_content_status($content_type, $content_id, AKISMET_CONTENT_STATUS_HAM); } if ($comment->status == COMMENT_NOT_PUBLISHED) { akismet_comment_operation($content_id, 'publish'); } } drupal_goto("node/$comment->nid", NULL, "comment-$comment->cid"); } else if ($content_type == 'node') { // @TODO: } drupal_not_found(); } /** * Check if specified content is marked as spam. * * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. */ function akismet_is_content_spam($content_type, $content_id) { return db_result(db_query("SELECT 1 FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id)); } /** * Mark content as spam or remove the mark. * * A previous check needs to be made in order to see if content is already marked as spam or not. * * @param string Content type; can be either 'node' or 'comment'. * @param integer Content ID; can be either a nid or a cid. * @param integer Content Status; it can be AKISMET_CONTENT_STATUS_SPAM or AKISMET_CONTENT_STATUS_HAM. */ function akismet_set_content_status($content_type, $content_id, $status) { if ($status == AKISMET_CONTENT_STATUS_HAM) { db_query("DELETE FROM {akismet_spam_marks} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id); } else if ($status == AKISMET_CONTENT_STATUS_SPAM) { db_query("INSERT INTO {akismet_spam_marks} (content_type, content_id, spam_created) VALUES ('%s', %d, %d)", $content_type, $content_id, time()); } } /** * Implementation of hook_settings(). */ function akismet_settings() { $form = array(); $enable_options = array('1' => t('Enabled'), '0' => t('Disabled')); $akismet_wpapikey = variable_get('akismet_wpapikey', ''); if (empty($akismet_wpapikey)) { $akismet_collapsed = FALSE; } else { $is_valid = akismet_api_cmd_verify_key($akismet_wpapikey); $akismet_collapsed = $is_valid; } if ($akismet_collapsed) { $akismet_collapsed = variable_get('akismet_connection_enabled', 1); } $form['general'] = array( '#type' => 'fieldset', '#title' => t('General settings'), '#collapsible' => TRUE, '#collapsed' => $akismet_collapsed ); $form['general']['akismet_wpapikey'] = array( '#type' => 'textfield', '#title' => t('WordPress.com API key'), '#size' => 30, '#maxlength' => 60, '#default_value' => $akismet_wpapikey, '#description' => t('Please, enter here your <a href="%wpapikey">WordPress.com API key</a>. If you don\'t have one already, you can get it by simply signing up for a free account at <a href="%wordpress-com">wordpress.com</a>. Note that this information is required in order to use the <a href="%akismet">Akismet Service</a>. Please, consult the <a href="%akismet-faq">Akismet FAQ</a> for further information.', array( '%wpapikey' => 'http://wordpress.com/api-keys/', '%wordpress-com' => 'http://wordpress.com', '%akismet' => 'http://akismet.com', '%akismet-faq' => 'http://akismet.com/faq/' )) ); if (!empty($akismet_wpapikey) && !$is_valid) { $form['general']['akismet_wpapikey']['#description'] .= '<div class="marker">'. t("<strong>WARNING: Your API Key doesn't seem to be valid!</strong>") .'</div>'; } $form['general']['akismet_connection_enabled'] = array( '#type' => 'radios', '#title' => t('Akismet connections'), '#options' => $enable_options, '#default_value' => variable_get('akismet_connection_enabled', 1), '#description' => t('<strong>This option must be enabled in order to perform real requests to the <a href="%akismet">Akismet Service</a>.</strong> You may want to disable this option for testing purposes, however. In this case, the <em>akismet module</em> will operate as normal, except sending real requests to the <a href="%akismet">Akismet Service</a>. ie. no automatic spam detection will be performed and no remote requests will be made when content is manually <em>marked</em>/<em>unmarked</em> as spam.<br />Note: regardless of this option, the <em>akismet module</em> will still connect, from this panel, to validate your <a href="%wpapikey">WordPress.com API key</a>, if specified.', array( '%akismet' => 'http://akismet.com', '%wpapikey' => 'http://wordpress.com/api-keys/' )) ); $interval_options = drupal_map_assoc(array(0, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval'); $interval_options[0] = t('never'); $form['general']['akismet_remove_spam_interval'] = array( '#type' => 'select', '#title' => t('Remove spam older than'), '#default_value' => variable_get('akismet_remove_spam_interval', 259200), '#options' => $interval_options, '#description' => t('Content marked as <em>spam</em> is still saved into database so it can be reviewed by content administrators. This option allows you to specify how long this information will be kept in the database. <em>Spam</em> older than the interval specified here will be automatically removed. Requires crontab.') ); $form['content'] = array( '#type' => 'fieldset', '#title' => t('Content settings'), '#collapsible' => TRUE, '#collapsed' => TRUE ); if (module_exist('comment')) { $form['content']['comment_options'] = array( '#type' => 'fieldset', '#title' => t('Comment options') ); $form['content']['comment_options']['akismet_check_comments'] = array( '#type' => 'radios', '#title' => t('Check for spam in comments'), '#options' => $enable_options, '#default_value' => variable_get('akismet_check_comments', 1), '#description' => t('Enable this option to automatically check for spam in comments. Regardless of this option, users with <em>%admin-comments</em> permission are still allowed to manually <em>submit spam</em>/<em>ham</em> (or <em>mark</em>/<em>unmark</em> when the <em>Akismet connections</em> options has been <em>disabled</em> above) from the links at the bottom of comments.', array( '%admin-comments' => t('administer comments') )) ); $form['content']['comment_options']['akismet_comment_links_enabled'] = array( '#type' => 'radios', '#title' => t('Links in comments'), '#options' => $enable_options, '#default_value' => variable_get('akismet_comment_links_enabled', 1), '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links in comments for operations such as <em>publish</em>, <em>unpublish</em>, <em>submit spam</em>, <em>submit ham</em>, etc. Note that <em>mark as ...</em> will be used (instead of <em>submit ...</em>) when the <em>Akismet connections</em> option has been <em>disabled</em> above.') ); } $form['content']['node_options'] = array( '#type' => 'fieldset', '#title' => t('Node options') ); $types = node_get_types(); $form['content']['node_options']['akismet_check_nodetypes'] = array( '#type' => 'checkboxes', '#title' => t('Check for spam in these content type(s)'), '#options' => $types, '#default_value' => variable_get('akismet_check_nodetypes', NULL), '#description' => t('Select the content types that are to be automatically checked for spam. Note that this options might only be useful when non administrators are allowed to create content. Regardless of these options, users with <em>%admin-nodes</em> permission are still allowed to manually <em>submit spam</em>/<em>ham</em> (or <em>mark</em>/<em>unmark</em> when the <em>Akismet connections</em> options has been <em>disabled</em> above) from the links at the bottom of nodes.', array( '%admin-nodes' => t('administer nodes') )) ); $form['content']['node_options']['akismet_node_links_enabled'] = array( '#type' => 'radios', '#title' => t('Links in nodes'), '#options' => $enable_options, '#default_value' => variable_get('akismet_node_links_enabled', 0), '#description' => t('Use this option to <em>enable</em> or <em>disable</em> links in nodes for operations such as <em>publish</em>, <em>unpublish</em>, <em>submit spam</em>, <em>submit ham</em>, etc. Note that <em>mark as ...</em> will be used (instead of <em>submit ...</em>) when the <em>Akismet connections</em> option has been <em>disabled</em> above.') ); return $form; } /** * Implementation of hook_cron(). */ function akismet_cron() { // Remove spam older than... db_query('DELETE FROM {akismet_spam_marks} WHERE spam_created < %d', time() - variable_get('akismet_remove_spam_interval', 259200)); } /** * Implementation of hook_form_alter(). */ function akismet_form_alter($form_id, &$form) { global $user; // If Akismet connections are not enabled, we have nothing else to do here. if (!variable_get('akismet_connection_enabled', 1)) { return; } // Detect node edit/add form. if (preg_match('#^(.*)_node_form$#', $form_id, $matches)) { // @TODO: return; } // Hook into comment edit/reply form. if ($form_id == 'comment_form' && variable_get('akismet_check_comments', 1)) { if (!user_access('administer comments')) { if (isset($form['cid']) && isset($form['cid']['#value']) && is_numeric($form['cid']['#value'])) { // This is the simple hook method, we already have the $cid. $form['#submit']['_akismet_comment_form_submit'] = array(); } else { // This is a bit more complex, because the user is creating a new comment, so // how do we get the $cid? See comments below, within our own submit callback. $form['#submit'] = array('_akismet_comment_form_submit' => array($form['#submit'])); } } } } /** * Comment form submit callback; check for spam. */ function _akismet_comment_form_submit($form_id, $form_values, $original_submit_callback = NULL) { // Our default destination. It doesn't need to override the original. $goto = NULL; // If the comment id being edited there's no problem to get the $cid. // In this case, the original #submit callback has already been called. if (isset($form_values['cid'])) { $cid = $form_values['cid']; } // However, if the comment is being created we'll try to get the $cid from the // return value of the original #submit callback. It's an array that customizes // the URL the user should be sent when the form is submitted. It contains the // $cid in the last argument, in the form of "comment-$cid", the hash of the URL. else { // Invoke the previous submit callbacks and capture their return values to try // to get the $cid from there. // The first critical part with this approach is that we have to emmulate the // $form argument that form.inc::drupal_submit_form() expects. At this point in // time, this function just uses the '#submit' element, but that could change in // the future. We have to keep an eye here, or think about a completely different // approach. Hopefully, this one will remain stable during the 4.x lifecycle. $form = array('#submit' => $original_submit_callback); // The second critical part is that we expect to find the $cid in the 3rd element // of the $goto array, as described above. $goto = drupal_submit_form($form_id, $form); if (is_array($goto) && isset($goto[2]) && preg_match('#^comment-([0-9]+)$#', $goto[2], $match)) { $cid = $match[1]; } } // Once we have a $cid, we can (try to) load the comment with all relevant // information that we need to make the Akismet request to check for spam. if ($cid) { $comment = _akismet_comment_load($cid, TRUE); // If we got a comment, send query to Akismet. if ($comment && akismet_api_cmd_comment_check($comment)) { // Oops! Akismet is telling us we got spammed, let's mark the comment as such. akismet_set_content_status('comment', $cid, AKISMET_CONTENT_STATUS_SPAM); // Unpublish the comment, if necessary. if ($comment->status == COMMENT_PUBLISHED) { akismet_comment_operation($cid, 'unpublish'); } // Since users won't see their replies published, show them a polite explanation on why. drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.')); // Add an entry to the watchdog log. watchdog('content', t('Comment spam, detected by akismet: %subject.', array('%subject' => theme('placeholder', $comment->subject))), WATCHDOG_WARNING, l(t('view'), "node/$comment->nid", NULL, NULL, "comment-$comment->cid")); } } // Return NULL or the destination returned by the original #submit callback. return $goto; } /** * Does a comment exist? * * @param int Comment ID. */ function _akismet_comment_exists($cid) { return db_result(db_query('SELECT 1 FROM {comments} WHERE cid = %d', $cid)); } /** * Load a comment. * * @param int Comment ID. * @param boolen Whether to load all possible comment data or not (optional, defaults to FALSE) */ function _akismet_comment_load($cid, $alldata = FALSE) { if ($alldata) { $comment = db_fetch_object(db_query(db_rewrite_sql('SELECT c.*, u.name AS registered_name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', 'c'), $cid)); if ($comment->uid) { $comment->name = $comment->registered_name; } } else { $comment = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $cid)); } return $comment; } /** * Wrapper for comment publish/unpublish operations. * * This function is based on comment.module::comment_admin_overview_submit() * so we might want to keep an eye there for future changes. */ function akismet_comment_operation($cid, $op) { static $operations = FALSE; // cached in case we need to come here more than once per request. if (!$operations) { $operations = comment_operations(); } // extract the appropriate database query operation $query = $operations[$op][1]; // perform the update action, then refresh node statistics db_query($query, $cid); $comment = _comment_load($cid); _comment_update_node_statistics($comment->nid); // Allow modules to respond to the updating of a comment. comment_invoke_comment($comment, $op); // Add an entry to the watchdog log. $action = ($op == 'unpublish' ? t('unpublished') : t('published')); watchdog('content', t('Comment %action: %subject.', array('%action' => $action, '%subject' => theme('placeholder', $comment->subject))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $comment->nid, NULL, NULL, 'comment-'. $comment->cid)); } /****************************************\ Akismet API implementation \****************************************/ define('AKISMET_API_HOST', 'rest.akismet.com'); define('AKISMET_API_PORT', 80); define('AKISMET_API_VERSION', '1.1'); define('AKISMET_USERAGENT', 'Drupal/4.7 | akismet.module/1.0'); /** * Akismet API: Key Verification rest.akismet.com/1.1/verify key * * @return boolean * Returns TRUE if API key is valid. */ function akismet_api_cmd_verify_key($key) { global $base_url; $request = "key=$key&blog=$base_url"; $response = _akismet_api_http_post($request, AKISMET_API_HOST, '/'. AKISMET_API_VERSION .'/verify-key'); return ('valid' == $response[1] ? TRUE : FALSE); } /** * Akismet API: Comment Check api-key.rest.akismet.com/1.1/comment-check * * @param object $comment * * @return boolean * Returns TRUE if the comment IS spam. */ function akismet_api_cmd_comment_check($comment) { $request_data = array_merge(_akismet_api_build_server_data(), _akismet_api_build_comment_data($comment)); $query_string = _akismet_api_get_query_string($request_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/comment-check'); return ('true' == $response[1] ? TRUE : FALSE); } /** * Akismet API: Submit Spam api-key.rest.akismet.com/1.1/submit-spam * * @param object $comment */ function akismet_api_cmd_submit_spam($comment) { $request_data = _akismet_api_build_comment_data($comment); $query_string = _akismet_api_get_query_string($request_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-spam'); } /** * Akismet API: Submit Ham api-key.rest.akismet.com/1.1/submit-ham * * @param object $comment */ function akismet_api_cmd_submit_ham($comment) { $request_data = _akismet_api_build_comment_data($comment); $query_string = _akismet_api_get_query_string($request_data); $host = variable_get('akismet_wpapikey', '') . AKISMET_API_HOST; $response = _akismet_api_http_post($query_string, $host, '/'. AKISMET_API_VERSION .'/submit-ham'); } /** * Prepare comment data that is to be sent along akismet requests. * * @param object $comment * * @return array */ function _akismet_api_build_comment_data($comment) { $comment_keys = array( // IP address of the comment submitter. 'user_ip' => (!empty($comment->hostname) ? $comment->hostname : $_SERVER['REMOTE_ADDR']), // User agent information of the comment submitter. 'user_agent' => $_SERVER['HTTP_USER_AGENT'], // The content of the HTTP_REFERER header should be sent here. 'referrer' => $_SERVER['HTTP_REFERER'], // The permanent location of the entry the comment was submitted to. 'permalink' => url("node/$comment->nid", NULL, "comment-$comment->cid", TRUE), // May be blank, comment, trackback, pingback, or a made up value like "registration". 'comment_type' => '', // Submitted name with the comment. 'comment_author' => $comment->name, // Submitted email address. 'comment_author_email' => $comment->mail, // Commenter URL. 'comment_author_url' => $comment->homepage, // The content that was submitted. 'comment_content' => $comment->comment ); $comment_data = array(); foreach ($comment_keys as $key => $value) { $comment_data[$key] = $value; } return $comment_data; } /** * Prepare $_SERVER data that is to be sent along akismet requests. * * @return array */ function _akismet_api_build_server_data() { // You may add more elements here, but they are often related to internal server // data that makes little sense to check whether a comment is spam or not. // Be sure to not send HTTP_COOKIE as it may compromise your user's privacy! static $safe_to_send = array( 'CONTENT_LENGTH', 'CONTENT_TYPE', 'HTTP_ACCEPT', 'HTTP_ACCEPT_CHARSET', 'HTTP_ACCEPT_ENCODING', 'HTTP_ACCEPT_LANGUAGE', 'HTTP_REFERER', 'HTTP_USER_AGENT', 'REMOTE_ADDR', 'REMOTE_PORT', 'SCRIPT_URI', 'SCRIPT_URL', 'SERVER_ADDR', 'SERVER_NAME', 'REQUEST_METHOD', 'REQUEST_URI', 'SCRIPT_NAME' ); // The contents of $_SERVER doesn't change between requests, // so we can have this cached in static storage. static $server_data; if (!$server_data) { $server_data = array(); foreach ($_SERVER as $key => $value) { if (in_array($key, $safe_to_send)) { $server_data[$key] = $value; } } } return $server_data; } /** * Convert an associative array into a string formatted according to akismet rules. * * @param array * * @return string */ function _akismet_api_get_query_string($array) { global $base_url; $string = 'blog='. $base_url . base_path(); foreach ($array as $key => $value) { $string .= '&' . $key . '=' . urlencode(stripslashes($value)); } return $string; } /** * Perform a HTTP POST request against the akismet server. * * @param string $request * The request. * @param string $host * The akismet host, prefixed with the API key (except when checking for the key itself). * @param string $path * The path where to perform the request. * * @return array * Headers in $response[0] and entity in $response[1] */ function _akismet_api_http_post($request, $host, $path) { $fsock_timeout = 3; $http_request = "POST $path HTTP/1.0\r\n" ."Host: $host\r\n" ."Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n" ."Content-Length: ". strlen($request) ."\r\n" ."User-Agent: ". AKISMET_USERAGENT ."\r\n" ."\r\n" .$request; $response = ''; if (false !== ($fs = @fsockopen($host, AKISMET_API_PORT, $errno, $errstr, $fsock_timeout))) { fwrite($fs, $http_request); while (!feof($fs)) { $response .= fgets($fs, 1160); // One TCP-IP packet } fclose($fs); $response = explode("\r\n\r\n", $response, 2); } return $response; } |
From: <php...@li...> - 2006-06-04 00:49:35
|
Update of /cvsroot/phpmix/drupal/modules/akismet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25128/akismet Log Message: Directory /cvsroot/phpmix/drupal/modules/akismet added to the repository |
From: <php...@li...> - 2006-06-03 20:30:04
|
Update of /cvsroot/phpmix/drupal/modules/smtp_checker In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22670 Modified Files: README.txt Log Message: Oops! Version here was different! Index: README.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/smtp_checker/README.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** README.txt 3 Jun 2006 20:27:52 -0000 1.2 --- README.txt 3 Jun 2006 20:29:54 -0000 1.3 *************** *** 4,8 **** ******************************************************************** Name : smtp_checker ! Version : 1.0.0 Author : markus_petrux [ http://www.phpmix.org ] Drupal : 4.7 --- 4,8 ---- ******************************************************************** Name : smtp_checker ! Version : 1.0.2 Author : markus_petrux [ http://www.phpmix.org ] Drupal : 4.7 |
From: <php...@li...> - 2006-06-03 20:28:05
|
Update of /cvsroot/phpmix/drupal/modules/smtp_checker In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21720 Modified Files: README.txt Log Message: Inserting module version to README.txt, for now. Index: README.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/smtp_checker/README.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README.txt 3 Jun 2006 16:12:33 -0000 1.1 --- README.txt 3 Jun 2006 20:27:52 -0000 1.2 *************** *** 3,9 **** D R U P A L M O D U L E ******************************************************************** ! Name : smtp_checker ! Author: markus_petrux [ http://www.phpmix.org ] ! Drupal: 4.7 ******************************************************************** --- 3,10 ---- D R U P A L M O D U L E ******************************************************************** ! Name : smtp_checker ! Version : 1.0.0 ! Author : markus_petrux [ http://www.phpmix.org ] ! Drupal : 4.7 ******************************************************************** |
From: <php...@li...> - 2006-06-03 20:27:31
|
Update of /cvsroot/phpmix/drupal/modules/session_protection In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21622 Modified Files: README.txt Log Message: Inserting module version to README.txt, for now. Index: README.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/session_protection/README.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README.txt 3 Jun 2006 16:12:33 -0000 1.1 --- README.txt 3 Jun 2006 20:27:20 -0000 1.2 *************** *** 3,12 **** D R U P A L M O D U L E ******************************************************************** ! Name : session_protection ! Author: markus_petrux [ http://www.phpmix.org ] ! Drupal: 4.7 ******************************************************************** DESCRIPTION: The session_protection module protect user sessions against hijacking attacks and offer a better method to protect from session fixation --- 3,14 ---- D R U P A L M O D U L E ******************************************************************** ! Name : session_protection ! Version : 1.0.0 ! Author : markus_petrux [ http://www.phpmix.org ] ! Drupal : 4.7 ******************************************************************** DESCRIPTION: + The session_protection module protect user sessions against hijacking attacks and offer a better method to protect from session fixation |
From: <php...@li...> - 2006-06-03 20:26:54
|
Update of /cvsroot/phpmix/drupal/modules/phpinfo In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21149 Modified Files: README.txt Log Message: Inserting module version to README.txt, for now. Index: README.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/phpinfo/README.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README.txt 3 Jun 2006 16:12:30 -0000 1.1 --- README.txt 3 Jun 2006 20:26:42 -0000 1.2 *************** *** 3,9 **** D R U P A L M O D U L E ******************************************************************** ! Name : phpinfo ! Author: markus_petrux [ http://www.phpmix.org ] ! Drupal: 4.7 ******************************************************************** --- 3,10 ---- D R U P A L M O D U L E ******************************************************************** ! Name : phpinfo ! Version : 1.0.0 ! Author : markus_petrux [ http://www.phpmix.org ] ! Drupal : 4.7 ******************************************************************** |
From: <php...@li...> - 2006-06-03 20:26:21
|
Update of /cvsroot/phpmix/drupal/modules/pathchecker In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21068 Modified Files: README.txt Log Message: Inserting module version to README.txt, for now. Index: README.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/pathchecker/README.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README.txt 3 Jun 2006 16:12:30 -0000 1.1 --- README.txt 3 Jun 2006 20:26:12 -0000 1.2 *************** *** 3,9 **** D R U P A L M O D U L E ******************************************************************** ! Name : pathchecker ! Author: markus_petrux [ http://www.phpmix.org ] ! Drupal: 4.7 ******************************************************************** --- 3,10 ---- D R U P A L M O D U L E ******************************************************************** ! Name : pathchecker ! Version : 1.0.0 ! Author : markus_petrux [ http://www.phpmix.org ] ! Drupal : 4.7 ******************************************************************** |
From: <php...@li...> - 2006-06-03 20:25:43
|
Update of /cvsroot/phpmix/drupal/modules/bypass_forced_preview In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20614 Modified Files: README.txt Log Message: Inserting module version to README.txt, for now. Index: README.txt =================================================================== RCS file: /cvsroot/phpmix/drupal/modules/bypass_forced_preview/README.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README.txt 3 Jun 2006 19:55:14 -0000 1.1 --- README.txt 3 Jun 2006 20:25:26 -0000 1.2 *************** *** 3,9 **** D R U P A L M O D U L E ******************************************************************** ! Name : bypass_forced_preview ! Author: markus_petrux [ http://www.phpmix.org ] ! Drupal: 4.7 ******************************************************************** --- 3,10 ---- D R U P A L M O D U L E ******************************************************************** ! Name : bypass_forced_preview ! Version : 1.0.0 ! Author : markus_petrux [ http://www.phpmix.org ] ! Drupal : 4.7 ******************************************************************** |
From: <php...@li...> - 2006-06-03 20:05:42
|
Update of /cvsroot/phpmix/wordpress In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10766 Added Files: LICENSE.txt Log Message: Import of license file. --- NEW FILE: LICENSE.txt --- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. |
From: <php...@li...> - 2006-06-03 20:05:31
|
Update of /cvsroot/phpmix/widgets In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10711 Added Files: LICENSE.txt Log Message: Import of license file. --- NEW FILE: LICENSE.txt --- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. |