예제 #1
0
 public function process_comment_headers($headers, $group_hash, $save = true)
 {
     /*
      *	We iterate over the provided headers (generated by
      *	$this->_get_headers() to a structure that is at the very
      *	minimum looking like this:
      *
      *	array (
      *		[0] => array (
      *				'Number': <int>
      *				'Subject': <string>
      *				'From': <string>
      *				'Date': <string>
      *				'Message-ID': <string>
      *				'Bytes': <int>
      *				'Lines': <int>
      *				'Epoch': <int>
      *			),
      *			...
      *		)
      *	From the structure above, we process our group hash and retrieve
      *	all the binary data we need on valid content.
      *
      *	A group_hash() record looks like this:
      *		array(
      *			array(
      *				'id': <int>,
      *				'key': <string>,
      *				'user': <string>,
      *				'email': <string>,
      *				'ref': <int>,
      *			),
      *			array(
      *				'id': <int>,
      *				'key': <string>,
      *				'user': <string>,
      *				'email': <string>,
      *				'ref': <int>,
      *			),
      *		)
      */
     if (!count($group_hash)) {
         // Nothing to process
         return [];
     }
     //
     // Prepare some general SQL Commands for saving later if all goes well
     //
     $db = new Settings();
     $rc = new ReleaseComments();
     // Comments
     $sql_new_cmt = "INSERT INTO release_comments (" . "id, sourceid, username, userid, gid, cid, isvisible, " . "releaseid, `text`, createddate, issynced, nzb_guid) VALUES (" . "NULL, %d, %s, 0, %s, %s, %d, 0, %s, %s, 1, %s)";
     $sql_upd_cmt = "UPDATE release_comments SET " . "isvisible = %d, `text` = %s" . "WHERE sourceid = %d AND gid = %s AND cid = %s AND nzb_guid = %s";
     $sql_fnd_cmt = "SELECT count(id) as cnt FROM release_comments " . "WHERE sourceid = %d AND gid = %s AND cid = %s";
     // Sync Times
     $sql_sync = "UPDATE spotnabsources SET lastupdate = %s " . "WHERE id = %d";
     $matches = Null;
     $processed = 0;
     $updates = 0;
     $inserts = 0;
     foreach ($headers as $header) {
         // Preform some general scanning the header to determine
         // if it could possibly be a valid post.
         if (!preg_match(SpotNab::FETCH_MSGID_REGEX, $header['Message-ID'], $matches)) {
             continue;
         }
         if ($matches['domain'] != SpotNab::SEGID_DOMAIN) {
             continue;
         }
         if ($matches['type'] != SpotNab::FETCH_COMMENT_TYPE) {
             continue;
         }
         // Now we check the subject line; it provides the first part of
         // the key to determining if we should handle the message or not
         if (!preg_match(SpotNab::FETCH_COMMENT_SUBJECT_REGEX, $header['Subject'], $matches)) {
             continue;
         }
         // We have a match; So populate potential variables
         $checksum = $matches['checksum'];
         $refdate = $matches['utcref'];
         $refdate_epoch = @strtotime($matches['utcref'] . " UTC");
         if ($refdate_epoch === false || $refdate_epoch < 0) {
             // Bad time specified
             continue;
         }
         // PreKey is used to attempt to run the decode algorithm
         // a head of time.. if we can decrypt this we can probably
         // assume the body will decode too (and won't be a waste of
         // time to download it)
         foreach ($group_hash as $hash) {
             // Track how many records we handled
             $processed++;
             // First check the ref date... if it's newer then what we've
             // already processed, then we'll just keep on chugging along.
             if ($refdate_epoch <= $hash['ref']) {
                 continue;
             }
             // Scan header information for supported matches
             if (!preg_match('/^(?P<user>[^<]+)<(?P<email>[^>]+)>$/', $header['From'], $matches)) {
                 continue;
             }
             // Match against our sources posts
             if (trim($matches['user']) != $hash['user']) {
                 continue;
             }
             if (trim($matches['email']) != $hash['email']) {
                 continue;
             }
             // If we reach here, we've found a header we can process
             // The next step is to download the header's body
             // We'll do some final verifications on it such as detect
             // if the checksum is okay, and verify that the timestamp
             // within the body matches that of the header... then we
             // can start processing the guts of the body.
             if ($save) {
                 // Download Body
                 $body = $this->_get_body($header['Group'], $header['Message-ID']);
                 if ($body === false) {
                     continue;
                 }
                 //echo "DEBUG Close Match:\n";
                 //print_r($header);
                 // Decode Body
                 $body = $this->decodePost($body, $hash['key']);
                 if ($body === false) {
                     continue;
                 }
                 // Decode failed
                 // Verify Body
                 if (!is_array($body)) {
                     continue;
                 }
                 // not any array
                 if (!(bool) count(array_filter(array_keys($body), 'is_string'))) {
                     continue;
                 }
                 // not an associative array
                 if (!array_key_exists('server', $body) || !array_key_exists('postdate_utc', $body)) {
                     continue;
                 }
                 // base structure missing
                 // Compare postdate_utc and ensure it matches header
                 // timestamp
                 if (preg_replace('/[^0-9]/', '', $body['postdate_utc']) != $refdate) {
                     continue;
                 }
                 // Comment Handling
                 if (array_key_exists('comments', $body) && is_array($body['comments'])) {
                     $rc = new ReleaseComments();
                     foreach ($body['comments'] as $comment) {
                         // Verify Comment is parseable
                         if (!is_array($comment)) {
                             continue;
                         }
                         // not an array
                         if (!count(array_filter(array_keys($comment)))) {
                             continue;
                         }
                         // not an associative array
                         // Store isvisible flag
                         $is_visible = 1;
                         if (array_key_exists('is_visible', $comment)) {
                             $is_visible = intval($comment['is_visible']) > 0 ? 1 : 0;
                         }
                         // Check that comment doesn't already exist
                         $res = $db->queryOneRow(sprintf($sql_fnd_cmt, $hash['id'], $db->escapeString($comment['gid']), $db->escapeString($comment['cid'])));
                         // Store Results in DB
                         if ($res && intval($res['cnt']) > 0) {
                             // Make some noise
                             echo '.';
                             $updates += $db->queryExec(sprintf($sql_upd_cmt, $is_visible, $db->escapeString($comment['comment']), $hash['id'], $db->escapeString($comment['gid']), $db->escapeString($comment['cid']), $db->escapeString($comment['gid']))) > 0 ? 1 : 0;
                         } else {
                             // Make some noise
                             echo '+';
                             // Perform Insert
                             $res = $db->queryInsert(sprintf($sql_new_cmt, $hash['id'], $db->escapeString($comment['username']), $db->escapeString($comment['gid']), $db->escapeString($comment['cid']), $is_visible, $db->escapeString($comment['comment']), $db->escapeString($this->utc2local($comment['postdate_utc'])), $db->escapeString($comment['gid'])));
                             $inserts += 1;
                         }
                         $rc->updateReleaseCommentCount($comment['gid']);
                     }
                 }
                 // Update spotnabsources table, set lastupdate to the
                 // timestamp parsed from the header.
                 $db->queryExec(sprintf($sql_sync, $db->escapeString($this->utc2local($body['postdate_utc'])), $hash['id']));
             } else {
                 // Debug non/save mode; mark update
                 $updates += 1;
             }
             // always break if we made it this far... no mater how many
             // other groups are being processed, we've already matched
             // for this article, so we don't need to process it for
             // other sources.
             break;
         }
     }
     return [$inserts, $updates];
 }