function do_posts($link) { global $globals; $info = SitesMgr::get_info(); $properties = SitesMgr::get_extended_properties(); syslog(LOG_INFO, "Meneame, posting {$link->uri}"); $url = $link->get_permalink($info->sub); echo "Posting {$url}: " . $globals['server_name'] . "\n"; // NEW format $image = false; if ($link->has_thumb()) { $media = $link->get_media(); if ($media && file_exists($media->pathname())) { $image = $media->pathname(); } } if ($globals['url_shortener']) { $short_url = $link->get_short_permalink(); } else { $short_url = $url; } if (!empty($properties['twitter_token']) && !empty($properties['twitter_token_secret']) && !empty($properties['twitter_consumer_key']) && !empty($properties['twitter_consumer_secret'])) { $r = false; $tries = 0; while (!$r && $tries < 4) { $r = twitter_post($properties, $link->title, $url, $image); $tries++; if (!$r) { sleep(4); } } } if (!empty($properties['facebook_token']) && !empty($properties['facebook_key']) && !empty($properties['facebook_secret'])) { $r = false; $tries = 0; while (!$r && $tries < 4) { $r = facebook_post($properties, $link); $tries++; if (!$r) { sleep(4); } } } /* if ($globals['pubsub']) { pubsub_post(); } */ }
// Compatibility with the old "search" query string if ($_REQUEST['search']) { $_REQUEST['q'] = $_REQUEST['search']; } // Sub if ($_REQUEST['sub']) { $sub_id = SitesMgr::get_id(mb_substr($_REQUEST['sub'], 20)); if ($sub_id) { SitesMgr::__init($sub_id); } else { die; } } else { $site_id = SitesMgr::my_id(); } $site_info = SitesMgr::get_info(); if ($site_info->sub && $site_info->owner > 0) { $site_info->name = $site_info->name; } if (!empty($_REQUEST['id']) && intval($_REQUEST['id']) > 0) { // // Comments // $id = intval($_REQUEST['id']); $comments = $db->get_col("SELECT comment_id FROM comments WHERE comment_link_id = {$id} ORDER BY comment_date DESC"); if ($comments) { list_all('comments', $comments, $title, $site_info); } } else { // // Links
function depublish($site_id) { // send back to queue links with too many negatives global $db, $globals; $days = 4; echo "STARTING depublish for {$site_id}\n"; $site_info = SitesMgr::get_info($site_id); $links = $db->get_col("select SQL_NO_CACHE link_id as id from links, sub_statuses where id = {$site_id} and status = 'published' and date > date_sub(now(), interval {$days} day) and date < date_sub(now(), interval 14 minute) and link = link_id and link_negatives > link_votes / 5"); if ($links) { $votes_clicks = $db->get_col("select SQL_NO_CACHE link_votes/counter from links, sub_statuses, link_clicks where sub_statuses.id = {$site_id} and status = 'published' and date > date_sub(now(), interval {$days} day) and link = link_id and link_clicks.id = link"); sort($votes_clicks); foreach ($links as $link) { $l = Link::from_db($link); $vc = $l->votes / $l->clicks; $prob = cdf($votes_clicks, $vc); // Count only those votes with karma > 6 to avoid abuses with new accounts with new accounts $negatives = (int) $db->get_var("select SQL_NO_CACHE sum(user_karma) from votes, users where vote_type='links' and vote_link_id={$l->id} and vote_date > from_unixtime({$l->date}) and vote_date > date_sub(now(), interval 24 hour) and vote_value < 0 and vote_user_id > 0 and user_id = vote_user_id and user_karma > " . $globals['depublish_negative_karma']); $positives = (int) $db->get_var("select SQL_NO_CACHE sum(user_karma) from votes, users where vote_type='links' and vote_link_id={$l->id} and vote_date > from_unixtime({$l->date}) and vote_value > 0 and vote_date > date_sub(now(), interval 24 hour) and vote_user_id > 0 and user_id = vote_user_id and user_karma > " . $globals['depublish_positive_karma']); echo "Candidate {$l->uri}\n karma: {$l->sub_karma} ({$l->karma}) negative karma: {$negatives} positive karma: {$positives}\n"; // Adjust positives to the probability of votes/clicks $c = 1 + (1 - $prob) * 0.5; $positives = $positives * $c; echo " probability: {$prob} New positives: {$positives} ({$c})\n"; if ($negatives > 10 && $negatives > $c * $l->sub_karma / 6 && $l->negatives > $c * $l->votes / 6 && $l->negatives > 5 && ($negatives > $positives || $negatives > $c * $l->sub_karma / 2 && $negatives > $positives / 2)) { echo "Queued again: {$l->id} negative karma: {$negatives} positive karma: {$positives}\n"; $karma_old = $l->sub_karma; $karma_new = intval($l->sub_karma / $globals['depublish_karma_divisor']); $l->status = 'queued'; $l->sub_karma = $l->karma = $karma_new; $db->query("update links set link_status='queued', link_date = link_sent_date, link_karma={$karma_new} where link_id = {$l->id}"); SitesMgr::deploy($l); // Add an annotation to show it in the logs $l->karma_old = $karma_old; $l->karma = $karma_new; $l->annotation = _('Retirada de portada'); $l->save_annotation('link-karma'); Log::insert('link_depublished', $l->id, $l->author); if (!$site_info->sub) { // Add the discard to log/event $user = new User($l->author); if ($user->read) { echo "{$user->username}: {$user->karma}\n"; $user->add_karma(-$globals['instant_karma_per_depublished'], _('Retirada de portada')); } // Increase karma to users that voted negative $ids = $db->get_col("select vote_user_id from votes where vote_type = 'links' and vote_link_id = {$l->id} and vote_user_id > 0 and vote_value < 0"); foreach ($ids as $id) { $u = new User($id); if ($u->read) { // Avoid abuse of users voting negative just to get more karma $voted = $db->get_var("select count(*) from logs where log_type = 'user_depublished_vote' and log_user_id = {$id} and log_date > date_sub(now(), interval 48 hour)"); if ($voted < 5) { $u->add_karma(0.2, _('Negativo a retirada de portada')); Log::insert('user_depublished_vote', $l->id, $id); } } } } /*********** * TODO: call for every site (as in promote) if ($globals['twitter_token'] || $globals['jaiku_user']) { if ($globals['url_shortener']) { $short_url = $l->get_short_permalink(); } else { $short_url = fon_gs($l->get_permalink()); } $text = _('Retirada de portada') . ': ' . $l->title; if ($globals['twitter_user'] && $globals['twitter_token']) { twitter_post($text, $short_url); } if ($globals['jaiku_user'] && $globals['jaiku_key']) { jaiku_post($text, $short_url); } } *******/ } } } }
function print_subs_form($selected = false) { global $db, $globals, $current_user; function id($s) { return $s->id; } if (!empty($globals['submnm'])) { $subs = false; } else { $subs = SitesMgr::get_sub_subs(); $ids = array_map('id', $subs); // A link in a sub is edited from another sub, or from the main site // Add its selected sub. if ($selected != false && !in_array($selected, $ids)) { $e = SitesMgr::get_info($selected); if ($e) { array_unshift($subs, $e); // Add to the form array_unshift($ids, $selected); // Avoid to show it again if subscribed to } } $extras = SitesMgr::get_subscriptions($current_user->user_id); // Don't repeat the same subs $subscriptions = array(); foreach ($extras as $s) { if (!in_array($s->id, $ids)) { $subscriptions[] = $s; } } } if ($selected == false) { $selected = SitesMgr::my_id(); } $vars = compact('selected', 'subs', 'subscriptions'); return Haanga::Load('form_subs.html', $vars); }
<?php $path = $globals['path']; $globals['submnm'] = preg_replace('/[^\\p{L}\\d_]/u', ':', $path[1]); include_once 'config.php'; $forbidden_routes = array('m', 'user', 'legal', 'notame', 'mobile', 'register', 'login', 'trends'); if (in_array($path[2], $forbidden_routes)) { // syslog(LOG_INFO, "Forbidden in subs: ".$path[2]); // Redirect to the root $uri = preg_split('/\\/+/', $_SERVER['REQUEST_URI'], 10, PREG_SPLIT_NO_EMPTY); $uri = array_slice($uri, 2); $uri = '/' . implode('/', $uri); header("Location: {$uri}"); die; } $globals['site_shortname'] = $globals['submnm']; if (empty($globals['submnm']) || !($info = SitesMgr::get_info())) { not_found(); } $globals['path'] = array_slice($path, 2); $globals['base_url'] .= $path[0] . '/' . $path[1] . '/'; if (!empty($routes[$path[2]])) { $res = (include './' . $routes[$path[2]]); if ($res === FALSE) { not_found($path[1]); } } else { // Try with story include './story.php'; }
function save_sub($id, &$errors) { global $current_user, $db; // Double check $owner = intval($_POST['owner']); if (!SitesMgr::can_edit($id)) { array_push($errors, _('usuario no autorizado a editar')); return false; } $site = SitesMgr::get_info(); $extended = SitesMgr::get_extended_properties($id); if ($_POST['created_from'] != $site->id) { array_push($errors, _('sitio erróneo')); } if ($owner != $current_user->user_id && !$current_user->admin) { array_push($errors, _('propietario erróneo')); } $name = mb_substr(clean_input_string($_POST['name']), 0, 12); if (mb_strlen($name) < 3 || !preg_match('/^\\p{L}[\\p{L}\\d_]+$/u', $name)) { array_push($errors, _('nombre erróneo') . ' ' . $_POST['name']); } $name_long = mb_substr(clean_text($_POST['name_long']), 0, 40); if (mb_strlen($name_long) < 6) { array_push($errors, _('título erróneo')); } $name = $db->escape($name); $name_long = $db->escape($name_long); if ($db->get_var("select count(*) from subs where name = '{$name}' and id != {$id}") > 0) { array_push($errors, _('nombre duplicado')); } $page_mode = $db->escape($_POST['page_mode']); if ($current_user->admin) { $enabled = intval($_POST['enabled']); $allow_main_link = intval($_POST['allow_main_link']); } else { // Keep the values $enabled = $site->enabled; $allow_main_link = $site->allow_main_link; $_POST['post_html'] = $extended['post_html']; } $nsfw = intval($_POST['nsfw']); $private = intval($_POST['private']); // Check the extended info foreach (array('no_link', 'no_anti_spam', 'allow_local_links', 'intro_max_len', 'intro_min_len') as $k) { if (isset($_POST[$k]) && $_POST[$k] !== '') { $_POST[$k] = intval($_POST[$k]); } } if ($_POST['intro_max_len'] > 5000) { $_POST['intro_max_len'] = 5000; } if (empty($errors)) { $db->transaction(); if ($id > 0) { $r = $db->query("update subs set owner = {$owner}, enabled = {$enabled}, allow_main_link = {$allow_main_link}, nsfw = {$nsfw}, name = '{$name}', name_long = '{$name_long}', private = {$private}, page_mode = '{$page_mode}' where id = {$id}"); } else { $r = $db->query("insert into subs (created_from, owner, nsfw, name, name_long, sub, private) values ({$site->id}, {$owner}, {$nsfw}, '{$name}', '{$name_long}', 1, {$private})"); $id = $db->insert_id; } if ($r && $id > 0) { // Copy values from first site $r = $db->query("update subs as a join subs as b on a.id = {$id} and b.id={$site->id} set a.server_name = b.server_name, a.base_url = b.base_url"); // Update copy_from if ($current_user->admin) { sub_copy_from($id, $_POST['copy_from']); } // Update colors $color_regex = '/^#[a-f0-9]{6}/i'; if (preg_match($color_regex, $_POST['color1'])) { $color1 = $db->escape($_POST['color1']); } else { $color1 = ''; } if (preg_match($color_regex, $_POST['color2'])) { $color2 = $db->escape($_POST['color2']); } else { $color2 = ''; } $db->query("update subs set color1 = '{$color1}', color2 = '{$color2}' where id = {$id}"); } if ($r && $id > 0) { SitesMgr::store_extended_properties($id, $_POST); $db->commit(); store_image($id); return $id; } else { array_push($errors, _('error actualizando la base de datos')); $db->rollback(); } } return false; }
function publish($link) { global $globals, $db; //return; if (DEBUG) { return; } // Calculate votes average // it's used to calculate and check future averages $votes_avg = (double) $db->get_var("select SQL_NO_CACHE avg(vote_value) from votes, users where vote_type='links' AND vote_link_id={$link->id} and vote_user_id > 0 and vote_value > 0 and vote_user_id = user_id and user_level !='disabled'"); if ($votes_avg < $globals['users_karma_avg']) { $link->votes_avg = max($votes_avg, $globals['users_karma_avg'] * 0.97); } else { $link->votes_avg = $votes_avg; } $link->status = 'published'; $link->date = $link->published_date = time(); $db->query("update links set link_status='published', link_date=now(), link_votes_avg={$link->votes_avg} where link_id={$link->id}"); SitesMgr::deploy($link); // Increase user's karma $user = new User($link->author); if ($user->read) { $user->add_karma($globals['instant_karma_per_published'], _('noticia publicada')); } // Add the publish event/log Log::insert('link_publish', $link->id, $link->author); $link->annotation .= _('publicación') . "<br/>"; $link->save_annotation('link-karma'); // Publish to all sub sites: this and children who import the link category $my_id = SitesMgr::my_id(); // Get all sites that are "children" and try to post links // And that "import" the link->category $sites = array_intersect(SitesMgr::get_children($my_id), SitesMgr::get_receivers($link->category)); // Add my own $sites[] = $my_id; foreach ($sites as $s) { $server_name = SitesMgr::get_info($s)->server_name; syslog(LOG_INFO, "Meneame, calling: " . dirname(__FILE__) . "/post_link.php {$server_name} {$link->id}"); passthru(dirname(__FILE__) . "/post_link.php {$server_name} {$link->id}"); } }
function do_header($title, $id = 'home', $options = false) { global $current_user, $dblang, $globals, $db; check_auth_page(); header('Content-Type: text/html; charset=utf-8'); header('X-Frame-Options: SAMEORIGIN'); header('X-UA-Compatible: IE=edge,chrome=1'); http_cache(); if (!empty($globals['link_id'])) { // Pingback autodiscovery // http://www.hixie.ch/specs/pingback/pingback header('X-Pingback: http://' . get_server_name() . $globals['base_url'] . 'xmlrpc.php'); } $globals['security_key'] = get_security_key(); setcookie('k', $globals['security_key'], 0, $globals['base_url']); if (!empty($_REQUEST['q'])) { $globals['q'] = $_REQUEST['q']; } /* if ($globals['greetings']) $greeting = array_rand($globals['greetings'], 1); else $greeting = _('hola'); */ if (!is_array($options)) { $left_options = array(); $left_options[] = new MenuOption(_('enviar historia'), $globals['base_url'] . 'submit.php', $id, _('enviar nueva historia')); $left_options[] = new MenuOption(_('portada'), $globals['base_url'], $id, _('página principal')); $left_options[] = new MenuOption(_('pendientes'), $globals['base_url'] . 'shakeit.php', $id, _('menear noticias pendientes')); $left_options[] = new MenuOption(_('populares'), $globals['base_url'] . 'topstories.php', $id, _('historias más votadas')); $left_options[] = new MenuOption(_('más visitadas'), $globals['base_url'] . 'topclicked.php', $id, _('historias más visitadas/leídas')); $left_options[] = new MenuOption(_('destacadas'), $globals['base_url'] . 'topactive.php', $id, _('historias más activas')); $right_options = array(); $right_options[] = new MenuOption(_('fisgona'), $globals['base_url'] . 'sneak.php', $id, _('visualizador en tiempo real')); $right_options[] = new MenuOption(_('nótame'), post_get_base_url(), $id, _('leer o escribir notas y mensajes privados')); $right_options[] = new MenuOption(_('galería'), 'javascript:fancybox_gallery(\'all\');', false, _('las imágenes subidas por los usuarios')); } else { $left_options = $options; $right_options = array(); //$right_options[] = new MenuOption(_('portada'), $globals['base_url'], '', _('página principal')); $right_options[] = new MenuOption(_('pendientes'), $globals['base_url'] . 'shakeit.php', '', _('menear noticias pendientes')); $right_options[] = new MenuOption(_('fisgona'), $globals['base_url'] . 'sneak.php', $id, _('visualizador en tiempo real')); $right_options[] = new MenuOption(_('nótame'), post_get_base_url(), $id, _('leer o escribir notas y mensajes privados')); $right_options[] = new MenuOption(_('galería'), 'javascript:fancybox_gallery(\'all\');', false, _('las imágenes subidas por los usuarios')); } $sites = $db->get_results("select * from subs where visible order by id asc"); $this_site = SitesMgr::get_info(); $vars = compact('title', 'greeting', 'id', 'left_options', 'right_options', 'sites', 'this_site'); return Haanga::Load('header.html', $vars); }
function update_link_karma($site, $link) { global $db, $globals; if (time() - $link->time_annotation('link-karma') < 75) { echo "ALREADY CALCULATED {$link->uri}, ignoring\n"; return 0; } $site_info = SitesMgr::get_info($site); echo "START {$site_info->name} WITH {$link->uri}\n"; $user = new User(); $user->id = $link->author; $user->read(); $karma_pos_user = 0; $karma_neg_user = 0; $karma_pos_ano = 0; User::calculate_affinity($link->author, $past_karma * 0.3); // Calculate the real karma for the link $link->calculate_karma(); $karma_new = $link->karma; $link->message = ''; $changes = 0; // TODO: $subs_coef is not available // if (DEBUG ) $link->message .= "Sub: $link->sub_id coef: ".$subs_coef[$link->sub_id]." Init values: previous: $link->old_karma calculated: $link->karma new: $karma_new<br>\n"; // Verify last published from the same site $hours = 8; $min_pub_coef = 0.8; $last_site_published = (int) $db->get_var("select SQL_NO_CACHE UNIX_TIMESTAMP(max(link_date)) from sub_statuses, links where id = {$site} and status = 'published' and date > date_sub(now(), interval {$hours} hour) and link_id = link and link_blog = {$link->blog} "); if ($last_site_published > 0) { $pub_coef = $min_pub_coef + (1 - $min_pub_coef) * (time() - $last_site_published) / (3600 * $hours); $karma_new *= $pub_coef; $link->message .= 'Last published: ' . intval((time() - $last_site_published) / 3600) . ' hours ago.<br/>'; } if ($ban = check_ban($link->url, 'hostname', false, true)) { // Check if the domain is banned $karma_new *= 0.5; $link->message .= 'Domain banned.<br/>'; $link->annotation .= _('dominio baneado') . ": " . $ban['comment'] . "<br/>"; } elseif ($user->level == 'disabled' || $user->level == 'autodisabled') { // Check if the user is banned disabled if ($user->level == 'autodisabled') { $link->message .= "{$user->username} disabled herself, penalized.<br/>"; $karma_new *= 0.2; } else { $link->message .= "{$user->username} disabled, probably due to abuses, penalized.<br/>"; $karma_new *= 0.4; } $link->annotation .= _('cuenta deshabilitada') . "<br/>"; } elseif (check_ban($link->url, 'punished_hostname', false, true)) { // Check domain and user punishments $karma_new *= 0.75; $link->message .= $globals['ban_message'] . '<br/>'; } // Check if it was depubished before $depublished = (int) $db->get_var("select count(*) from logs where log_type = 'link_depublished' and log_ref_id = {$link->id}"); if ($depublished > 0) { $karma_new *= 0.4; $link->message .= 'Previously depublished' . '<br/>'; $link->annotation .= _('previamente quitada de portada') . "<br/>"; } // Check if the are previously published during last hours from the same sub if ($link->sub_id > 0 && $link->is_sub && $link->sub_owner > 0 && $link->sub_id != $site && $site_info->owner == 0) { $sub_published = $db->get_var("select UNIX_TIMESTAMP(date) from sub_statuses where id = {$site} and origen = {$link->sub_id} and status = 'published' and date > date_sub(now(), interval 24 hour) order by date desc limit 1"); if ($sub_published > 0) { $m_diff = intval((time() - $sub_published) / 60); $c = min(1, max(0.3, $m_diff / 1440)); $karma_new *= $c; $link->message .= 'Published from the same sub, c' . sprintf(': %4.2f <br/>', $c); $link->annotation .= _('publicada del mismo sub recientemente, coeficiente') . sprintf(': %4.2f <br/>', $c); } } $link->karma = round($karma_new); /// Commons votes if ($link->karma > 20) { $days = 7; $commons_votes = $db->get_col("select SQL_NO_CACHE value from sub_statuses, link_commons where id = {$site} and status = 'published' and sub_statuses.date > date_sub(now(), interval {$days} day) and link_commons.link = sub_statuses.link order by value asc"); $common = $link->calculate_common_votes(); echo "Calculating diversity ({$common}-" . count($commons_votes) . ")\n"; if ($common != false && $commons_votes && count($commons_votes) > 5) { $common_probability = cdf($commons_votes, $common); $p = round($common_probability, 2); echo "common: {$common} common_probability: {$common_probability}\n"; $link->common_probability = $common_probability; $link->message .= 'Voters density: ' . sprintf("%5.2f", $common) . ' diversity coef: ' . sprintf("%3.2f%%", (1 - $common_probability) * 100) . " Probability: {$p}<br/>"; $link->annotation .= _('Densidad diversidad') . ': ' . sprintf("%5.2f", $common) . ' ' . _('coeficiente') . ": " . sprintf("%3.2f%%", (1 - $common_probability) * 100) . " (" . _('probabilidad') . ": {$p})<br/>"; // Bonus for diversity $c = $common_probability / 0.5; if ($c <= 1) { $c = 1 - $c; if ($link->low_karma_perc > 60) { $low_karma_coef = (50 - ($link->low_karma_perc - 50)) / 50; } else { $low_karma_coef = 1; } $bonus = round($c * 0.5 * $link->karma * $low_karma_coef * (1 - 5 * $link->negatives / $link->votes)); echo "BONUS: {$link->karma} {$p}, {$c} -> {$bonus} ({$link->low_karma_perc}, {$low_karma_coef}, {$link->negatives}/{$link->votes})\n"; } else { // Decrease for high affinity between voters $c = $c - 1; $bonus = -round($c * 0.5 * $link->karma); echo "PENALIZATION: {$link->karma} {$p}, {$c} -> {$bonus}\n"; } if (abs($bonus) > 10) { $old = $link->karma; $link->karma += $bonus; $link->annotation .= _('Karma por diversidad') . ": {$old} -> {$link->karma}<br/>"; } } } // check differences, if > 4 store it if (abs($link->old_karma - $link->karma) > 6) { // Check percentage of low karma votes if difference > 20 (to avoid sending too many messages if ($link->old_karma > $link->karma + 20 && !empty($globals['adm_email']) && intval($link->low_karma_perc) >= 90 && $link->votes > 50) { echo "LOW KARMA WARN {$link->uri}\n"; $subject = _('AVISO: enlace con muchos votos de karma menor que la media'); $body = "Perc: {$link->low_karma_perc}% User votes: {$link->votes} Negatives: {$link->negatives}\n\n"; $body .= $link->get_permalink(); mail($globals['adm_email'], $subject, $body); } $link->message = sprintf("updated karma: %6d (%d, %d, %d) -> %-6d<br/>\n", $link->old_karma, $link->votes, $link->anonymous, $link->negatives, $link->karma) . $link->message; //$link->annotation .= _('ajuste'). ": $link->old_karma -> $link->karma <br/>"; if ($link->old_karma > $link->karma) { $changes = 1; } else { $changes = 2; } // increase if (!DEBUG) { $link->save_annotation('link-karma', $site_info->name); // Update relevant values $db->query("UPDATE links set link_karma={$link->karma}, link_votes_avg={$link->votes_avg} WHERE link_id={$link->id}"); } else { $link->message .= "To store: previous: {$link->old_karma} new: {$link->karma}<br>\n"; } } return $changes; }
function do_submit1() { global $db, $dblang, $current_user, $globals, $errors, $site_properties, $site_key; $site_info = SitesMgr::get_info(); $new_user = false; if (empty($_POST['url']) && empty($site_properties['no_link'])) { add_submit_error(_('debe especificar enlace')); return false; } if (!empty($_POST['url'])) { if (!empty($site_properties['no_anti_spam'])) { $anti_spam = false; } else { $anti_spam = true; } $url = clean_input_url(urldecode($_POST['url'])); $url = preg_replace('/#[^\\/]*$/', '', $url); // Remove the "#", people just abuse $url = preg_replace('/^http:\\/\\/http:\\/\\//', 'http://', $url); // Some users forget to delete the foo http:// if (!preg_match('/^\\w{3,6}:\\/\\//', $url)) { // http:// forgotten, add it $url = 'http://' . $url; } // check the URL is OK and that it resolves $url_components = @parse_url($url); if (!$url_components || !$url_components['host'] || gethostbyname($url_components['host']) == $url_components['host']) { add_submit_error(_('URL o nombre de servidor erróneo'), _('el nombre del servidor es incorrecto o éste tiene problemas para resolver el nombre')); syslog(LOG_NOTICE, "Meneame, hostname error ({$current_user->user_login}): {$url}"); return false; } if (!check_link_key()) { add_submit_error(_('clave incorrecta')); return false; } } else { $anti_spam = false; } // Check the user does not have too many drafts $minutes = intval($globals['draft_time'] / 60) + 10; $drafts = (int) $db->get_var("select count(*) from links where link_author={$current_user->user_id} and link_date > date_sub(now(), interval {$minutes} minute) and link_status='discard' and link_votes = 0"); if ($drafts > $globals['draft_limit']) { add_submit_error(_('demasiados borradores'), _('has hecho demasiados intentos, debes esperar o continuar con ellos desde la') . ' <a href="queue?meta=_discarded">' . _('cola de descartadas') . '</a></p>'); syslog(LOG_NOTICE, "Meneame, too many drafts ({$current_user->user_login}): " . $_REQUEST['url']); return false; } // Delete dangling drafts if ($drafts > 0) { $db->query("delete from links where link_author={$current_user->user_id} and link_date > date_sub(now(), interval 30 minute) and link_date < date_sub(now(), interval 10 minute) and link_status='discard' and link_votes = 0"); } $new_user = false; if ($anti_spam) { // Number of links sent by the user $total_sents = (int) $db->get_var("select count(*) from links where link_author={$current_user->user_id}") - $drafts; if ($total_sents > 0) { $sents = (int) $db->get_var("select count(*) from links where link_author={$current_user->user_id} and link_date > date_sub(now(), interval 60 day)") - $drafts; } else { $new_user = true; $sents = 0; } $register_date = $current_user->Date(); if ($globals['now'] - $register_date < $globals['new_user_time']) { $new_user = true; } if ($globals['min_karma_for_links'] > 0 && $current_user->user_karma < $globals['min_karma_for_links']) { add_submit_error(_('no tienes el mínimo de karma para enviar una nueva historia')); return false; } // Check for banned IPs if (($ban = check_ban($globals['user_ip'], 'ip', true)) || ($ban = check_ban_proxy())) { if ($ban['expire'] > 0) { $expires = _('caduca') . ': ' . get_date_time($ban['expire']); } else { $expires = ''; } add_submit_error(_('dirección IP no permitida para enviar'), $expires); syslog(LOG_NOTICE, "Meneame, banned IP " . $globals['user_ip'] . " ({$current_user->user_login}): {$url}"); return false; } } // END anti_spam // check that a new user also votes, not only sends links // it requires $globals['min_user_votes'] votes if ($new_user && $globals['min_user_votes'] > 0 && $current_user->user_karma < $globals['new_user_karma']) { $user_votes_total = (int) $db->get_var("select count(*) from votes where vote_type='links' and vote_user_id={$current_user->user_id}"); $user_votes = (int) $db->get_var("select count(*) from votes where vote_type='links' and vote_date > date_sub(now(), interval 72 hour) and vote_user_id={$current_user->user_id}"); $user_links = 1 + $db->get_var("select count(*) from links where link_author={$current_user->user_id} and link_date > date_sub(now(), interval 24 hour) and link_status != 'discard'"); $total_links = (int) $db->get_var("select count(*) from links where link_date > date_sub(now(), interval 24 hour) and link_status = 'queued'"); if ($sents == 0) { // If is a new user, requires more votes, to avoid spam $min_votes = $globals['min_user_votes']; } else { $min_votes = min(4, intval($total_links / 20)) * $user_links; } if (!$current_user->admin && $user_votes < $min_votes) { $needed = $min_votes - $user_votes; if ($new_user) { add_submit_error(_('¿es la primera vez que envías una historia?'), _('necesitas como mínimo') . " {$needed} " . _('votos')); } else { add_submit_error(_('no tienes el mínimo de votos necesarios para enviar una nueva historia'), _('necesitas votar como mínimo a') . " {$needed} " . _('envíos')); } add_submit_error(_('no votes de forma apresurada, penaliza el karma'), '<a href="' . $globals['base_url'] . 'queue" target="_blank">' . _('haz clic aquí para ir a votar') . '</a>'); return false; } } if ($anti_spam) { // Don't allow to send a link by a clone $hours = intval($globals['user_links_clon_interval']); $clones = $current_user->get_clones($hours + 1); if ($hours > 0 && $clones) { $l = implode(',', $clones); $c = (int) $db->get_var("select count(*) from links where link_status!='published' and link_date > date_sub(now(), interval {$hours} hour) and link_author in ({$l})"); if ($c > 0) { add_submit_error(_('ya se envió con otro usuario «clon» en las últimas horas') . ", " . _('disculpa las molestias')); syslog(LOG_NOTICE, "Meneame, clon submit ({$current_user->user_login}): " . $_REQUEST['url']); return false; } } // Check the number of links sent by a user $queued_24_hours = (int) $db->get_var("select count(*) from links, subs, sub_statuses where status!='published' and date > date_sub(now(), interval 24 hour) and link_author={$current_user->user_id} and sub_statuses.link=link_id and subs.id = sub_statuses.id and sub_statuses.origen = sub_statuses.id and subs.parent=0 and subs.owner = 0"); if ($globals['limit_user_24_hours'] && $queued_24_hours > $globals['limit_user_24_hours']) { add_submit_error(_('debes esperar, tienes demasiados envíos en cola de las últimas 24 horas') . " ({$queued_24_hours}), " . _('disculpa las molestias')); syslog(LOG_NOTICE, "Meneame, too many queued in 24 hours ({$current_user->user_login}): " . $_REQUEST['url']); return false; } // Check the number of links sent by the user in the last minutes $enqueued_last_minutes = (int) $db->get_var("select count(*) from links where link_status='queued' and link_date > date_sub(now(), interval 3 minute) and link_author={$current_user->user_id}"); if ($current_user->user_karma > $globals['limit_3_minutes_karma']) { $enqueued_limit = $globals['limit_3_minutes'] * 1.5; } else { $enqueued_limit = $globals['limit_3_minutes']; } if ($enqueued_last_minutes > $enqueued_limit) { add_submit_error(_('exceso de envíos'), _('se han enviado demasiadas historias en los últimos 3 minutos') . " ({$enqueued_last_minutes} > {$enqueued_limit}), " . _('disculpa las molestias')); syslog(LOG_NOTICE, "Meneame, too many queued ({$current_user->user_login}): " . $_REQUEST['url']); return false; } // avoid spams, an extra security check // it counts the numbers of links in the last hours if ($new_user) { $user_links_limit = $globals['new_user_links_limit']; $user_links_interval = intval($globals['new_user_links_interval'] / 3600); } else { $user_links_limit = $globals['user_links_limit']; $user_links_interval = intval($globals['user_links_interval'] / 3600); } $same_user = (int) $db->get_var("select count(*) from links where link_date > date_sub(now(), interval {$user_links_interval} hour) and link_author={$current_user->user_id}") - $drafts; $same_ip = (int) $db->get_var("select count(*) from links where link_date > date_sub(now(), interval {$user_links_interval} hour) and link_ip = '" . $globals['user_ip'] . "'") - $drafts; if ($same_user > $user_links_limit || $same_ip > $user_links_limit) { add_submit_error(_('debes esperar, ya se enviaron varias con el mismo usuario o dirección IP')); return false; } // avoid users sending continuous "rubbish" or "propaganda", specially new users // it takes in account the number of positive votes in the last six hours if ($same_user > 1 && $current_user->user_karma < $globals['karma_propaganda']) { $positives_received = $db->get_var("select sum(link_votes) from links where link_date > date_sub(now(), interval {$user_links_interval} hour) and link_author = {$current_user->user_id}"); $negatives_received = $db->get_var("select sum(link_negatives) from links where link_date > date_sub(now(), interval {$user_links_interval} hour) and link_author = {$current_user->user_id}"); if ($negatives_received > 10 && $negatives_received > $positives_received * 1.5) { add_submit_error(_('debes esperar, has tenido demasiados votos negativos en tus últimos envíos')); return false; } } } // END anti_spam $link = new Link(); $link->url = $url; $link->is_new = true; // Disable several options in the editing form $link->status = 'discard'; $link->author = $current_user->user_id; if (!empty($site_properties['rules']) && $site_properties['no_link'] == 2) { $link->rules = LCPBase::html($site_properties['rules']); } $edit = false; if (!empty($link->url)) { if (report_duplicated($url)) { return true; } // Don't output error messages if (!$link->check_url($url, $anti_spam, true) || !$link->get($url, null, $anti_spam)) { $e = _('URL erróneo o no permitido') . ': '; if ($link->ban && $link->ban['match']) { $e .= $link->ban['match']; } else { $e .= $link->url; } add_submit_error($e, _('Razón') . ': ' . $link->ban['comment']); if ($link->ban['expire'] > 0) { add_submit_error($e, _('caduca') . ': ' . get_date_time($link->ban['expire'])); } return false; } // If the URL has changed, check again is not dupe if ($link->url != $url && report_duplicated($link->url)) { return; } $link->randkey = intval($_POST['randkey']); if (!$link->valid) { $e = _('error leyendo el url') . ': ' . htmlspecialchars($url); // Dont allow new users with low karma to post wrong URLs if ($current_user->user_karma < 7 && $current_user->user_level == 'normal' && !$site_info->owner) { add_submit_error($e, _('URL inválido, incompleto o no permitido. Está fuera de línea, o tiene mecanismos antibots.')); return false; } add_submit_error($e, _('no es válido, está fuera de línea, o tiene mecanismos antibots. <strong>Continúa</strong>, pero asegúrate que sea correcto')); } if (!$link->pingback()) { $link->trackback(); } $link->trackback = htmlspecialchars($link->trackback); $link->create_blog_entry(); $blog = new Blog(); $blog->id = $link->blog; $blog->read(); $blog_url_components = @parse_url($blog->url); $blog_url = $blog_url_components['host'] . $blog_url_components['path']; } if ($anti_spam) { // Now we check again against the blog table // it's done because there could be banned blogs like http://lacotelera.com/something if ($ban = check_ban($blog->url, 'hostname', false, true)) { $e = _('URL inválido') . ': ' . htmlspecialchars($url); add_submit_error($e, _('el sitio') . ' ' . $ban['match'] . ' ' . _('está deshabilitado') . ' (' . $ban['comment'] . ')'); if ($ban['expire'] > 0) { add_submit_error($e, _('caduca') . ': ' . get_date_time($ban['expire'])); } syslog(LOG_NOTICE, "Meneame, banned site ({$current_user->user_login}): {$blog->url} <- " . $_REQUEST['url']); return false; } // check for users spamming several sites and networks // it does not allow a low "entropy" if ($sents > 30) { $ratio = (double) $db->get_var("select count(distinct link_blog)/count(*) from links where link_author={$current_user->user_id} and link_date > date_sub(now(), interval 60 day)"); $threshold = 1 / log($sents, 2); if ($ratio < $threshold) { if ($db->get_var("select count(*) from links where link_author={$current_user->user_id} and link_date > date_sub(now(), interval 60 day) and link_blog = {$blog->id}") > 2) { syslog(LOG_NOTICE, "Meneame, forbidden due to low entropy: {$ratio} < {$threshold} ({$current_user->user_login}): {$link->url}"); add_submit_error(_('ya has enviado demasiados enlaces a los mismos sitios'), _('varía las fuentes, podría ser considerado spam')); return false; } } } // Check the user does not send too many images or vídeos // they think this is a fotolog if ($sents > 5 && ($link->content_type == 'image' || $link->content_type == 'video')) { $image_links = intval($db->get_var("select count(*) from links, subs, sub_statuses where link_author={$current_user->user_id} and link_date > date_sub(now(), interval 60 day) and link_content_type in ('image', 'video') and sub_statuses.link=link_id and subs.id = sub_statuses.id and sub_statuses.origen = sub_statuses.id and subs.parent=0 and subs.owner = 0")); if ($image_links > $sents * 0.8) { syslog(LOG_NOTICE, "Meneame, forbidden due to too many images or video sent by user ({$current_user->user_login}): {$link->url}"); add_submit_error(_('ya has enviado demasiadas imágenes o vídeos')); return false; } } // Avoid users sending too many links to the same site in last hours $hours = 24; $same_blog = $db->get_var("select count(*) from links where link_date > date_sub(now(), interval {$hours} hour) and link_author={$current_user->user_id} and link_blog={$link->blog} and link_votes > 0"); if ($same_blog >= $globals['limit_same_site_24_hours']) { syslog(LOG_NOTICE, "Meneame, forbidden due to too many links to the same site in last {$hours} hours ({$current_user->user_login}): {$link->url}"); add_submit_error(_('demasiados enlaces al mismo sitio en las últimas horas')); return false; } // avoid auto-promotion (autobombo) $minutes = 30; $same_blog = $db->get_var("select count(*) from links where link_date > date_sub(now(), interval {$minutes} minute) and link_author={$current_user->user_id} and link_blog={$link->blog} and link_votes > 0"); if ($same_blog > 0 && $current_user->user_karma < 12) { syslog(LOG_NOTICE, "Meneame, forbidden due to short period between links to same site ({$current_user->user_login}): {$link->url}"); add_submit_error(_('ya has enviado un enlace al mismo sitio hace poco tiempo'), _('debes esperar') . " {$minutes} " . _('minutos entre cada envío al mismo sitio.') . ', ' . '<a href="' . $globals['base_url_general'] . 'faq-' . $dblang . '.php">' . _('lee el FAQ') . '</a>'); return false; } // Avoid spam (autobombo), count links in last two months $same_blog = $db->get_var("select count(*) from links where link_author={$current_user->user_id} and link_date > date_sub(now(), interval 60 day) and link_blog={$link->blog}"); $check_history = $sents > 3 && $same_blog > 0 && ($ratio = $same_blog / $sents) > 0.5; if ($check_history) { $e = _('has enviado demasiados enlaces a') . " {$blog->url}"; if ($sents > 5 && $ratio > 0.75) { add_submit_error($e, _('has superado los límites de envíos de este sitio')); // don't allow to continue syslog(LOG_NOTICE, "Meneame, warn, high ratio, process interrumped ({$current_user->user_login}): {$link->url}"); return false; } else { add_submit_error($e, _('continúa, pero ten en cuenta podría recibir votos negativos') . ', ' . '<a href="' . $globals['base_url'] . $globals['legal'] . '">' . _('condiciones de uso') . '</a>'); syslog(LOG_NOTICE, "Meneame, warn, high ratio, continue ({$current_user->user_login}): {$link->url}"); } } if (!$site_info->owner) { // Only for the main subs $links_12hs = $db->get_var("select count(*) from links, subs, sub_statuses where link_date > date_sub(now(), interval 12 hour) and sub_statuses.link=link_id and subs.id = sub_statuses.id and sub_statuses.origen = sub_statuses.id and subs.parent=0 and subs.owner = 0"); // check there is no an "overflow" from the same site $site_links = intval($db->get_var("select count(*) from links, subs, sub_statuses where link_date > date_sub(now(), interval 12 hour) and link_blog={$link->blog} and link_status in ('queued') and sub_statuses.link=link_id and subs.id = sub_statuses.id and sub_statuses.origen = sub_statuses.id and subs.parent=0 and subs.owner = 0")); if ($site_links > 10 && $site_links > $links_12hs * 0.05) { // Only 5% from the same site syslog(LOG_NOTICE, "Meneame, forbidden due to overflow to the same site ({$current_user->user_login}): {$link->url}"); add_submit_error(_('hay en cola demasiados envíos del mismo sitio, espera unos minutos por favor'), _('total en 12 horas') . ": {$site_links} , " . _('el máximo actual es') . ': ' . intval($links_12hs * 0.05)); return false; } // check there is no an "overflow" of images if ($link->content_type == 'image' || $link->content_type == 'video') { $image_links = intval($db->get_var("select count(*) from links, subs, sub_statuses where link_date > date_sub(now(), interval 12 hour) and link_content_type in ('image', 'video') and sub_statuses.link=link_id and subs.id = sub_statuses.id and sub_statuses.origen = sub_statuses.id and subs.parent=0 and subs.owner = 0")); if ($image_links > 5 && $image_links > $links_12hs * 0.15) { // Only 15% images and videos syslog(LOG_NOTICE, "Meneame, forbidden due to overflow images ({$current_user->user_login}): {$link->url}"); add_submit_error(_('ya se han enviado demasiadas imágenes o vídeos, espera unos minutos por favor'), _('total en 12 horas') . ": {$image_links} , " . _('el máximo actual es') . ': ' . intval($links_12hs * 0.05)); return false; } } if ($ban = check_ban($link->url, 'punished_hostname', false, true)) { add_submit_error(_('Aviso') . ' ' . $ban['match'] . ': <em>' . $ban['comment'] . '</em>', _('mejor enviar el enlace a la fuente original')); } } } // END anti_spam // Now stores new draft $link->sent_date = $link->date = time(); if (empty($_POST['randkey']) && !empty($site_properties['no_link'])) { $link->randkey = rand(10000, 10000000); $link->key = md5($link->randkey . $current_user->user_id . $current_user->user_email . $site_key . get_server_name()); } else { $link->randkey = $_POST['randkey']; $link->key = $_POST['key']; } $link->store(); $link->url_title = mb_substr($link->url_title, 0, 200); if (mb_strlen($link->url_description) > 40) { $link->content = $link->url_description; } $link->site_properties = $site_properties; $link->chars_left = $site_properties['intro_max_len'] - mb_strlen(html_entity_decode($link->content, ENT_COMPAT, 'UTF-8'), 'UTF-8'); Haanga::Load('link/submit1.html', compact('link', 'errors')); return true; }