- /**
- * Poll DFRN contacts
- *
- * @param array $contact The personal contact entry
- * @param string $updated The updated date
- * @return string polled XML
- * @throws \Exception
- */
- private static function pollDFRN(array $contact, $updated)
- {
- $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
- if (intval($contact['duplex']) && $contact['dfrn-id']) {
- $idtosend = '0:' . $orig_id;
- }
- if (intval($contact['duplex']) && $contact['issued-id']) {
- $idtosend = '1:' . $orig_id;
- }
-
- // they have permission to write to us. We already filtered this in the contact query.
- $perm = 'rw';
-
- // But this may be our first communication, so set the writable flag if it isn't set already.
- if (!intval($contact['writable'])) {
- $fields = ['writable' => true];
- DBA::update('contact', $fields, ['id' => $contact['id']]);
- }
-
- $last_update = (($contact['last-update'] <= DBA::NULL_DATETIME)
- ? DateTimeFormat::utc('now - 7 days', DateTimeFormat::ATOM)
- : DateTimeFormat::utc($contact['last-update'], DateTimeFormat::ATOM)
- );
-
- $url = $contact['poll'] . '?dfrn_id=' . $idtosend
- . '&dfrn_version=' . DFRN_PROTOCOL_VERSION
- . '&type=data&last_update=' . $last_update
- . '&perm=' . $perm;
-
- $curlResult = DI::httpRequest()->get($url);
-
- if (!$curlResult->isSuccess() && ($curlResult->getErrorNumber() == CURLE_OPERATION_TIMEDOUT)) {
- // set the last-update so we don't keep polling
- self::updateContact($contact, ['failed' => true, 'last-update' => $updated]);
- Contact::markForArchival($contact);
- Logger::log('Contact archived');
- return false;
- }
-
- $handshake_xml = $curlResult->getBody();
- $html_code = $curlResult->getReturnCode();
-
- Logger::log('handshake with url ' . $url . ' returns xml: ' . $handshake_xml, Logger::DATA);
-
- if (!strlen($handshake_xml) || ($html_code >= 400) || !$html_code) {
- // dead connection - might be a transient event, or this might
- // mean the software was uninstalled or the domain expired.
- // Will keep trying for one month.
- Logger::log("$url appears to be dead - marking for death ");
-
- // set the last-update so we don't keep polling
- $fields = ['failed' => true, 'last-update' => $updated, 'failure_update' => $updated];
- self::updateContact($contact, $fields);
- Contact::markForArchival($contact);
- return false;
- }
-
- if (!strstr($handshake_xml, '<')) {
- Logger::log('response from ' . $url . ' did not contain XML.');
-
- $fields = ['failed' => true, 'last-update' => $updated, 'failure_update' => $updated];
- self::updateContact($contact, $fields);
- Contact::markForArchival($contact);
- return false;
- }
-
- $res = XML::parseString($handshake_xml);
-
- if (!is_object($res)) {
- Logger::info('Unparseable response', ['url' => $url]);
-
- $fields = ['failed' => true, 'last-update' => $updated, 'failure_update' => $updated];
- self::updateContact($contact, $fields);
- Contact::markForArchival($contact);
- return false;
- }
-
- if (intval($res->status) == 1) {
- // we may not be friends anymore. Will keep trying for one month.
- Logger::log("$url replied status 1 - marking for death ");
-
- // set the last-update so we don't keep polling
- $fields = ['failed' => true, 'last-update' => $updated, 'failure_update' => $updated];
- self::updateContact($contact, $fields);
- Contact::markForArchival($contact);
- } elseif ($contact['term-date'] > DBA::NULL_DATETIME) {
- Contact::unmarkForArchival($contact);
- }
-
- if ((intval($res->status) != 0) || !strlen($res->challenge) || !strlen($res->dfrn_id)) {
- // set the last-update so we don't keep polling
- DBA::update('contact', ['last-update' => $updated], ['id' => $contact['id']]);
- Logger::log('Contact status is ' . $res->status);
- return false;
- }
-
- if (((float)$res->dfrn_version > 2.21) && ($contact['poco'] == '')) {
- $fields = ['poco' => str_replace('/profile/', '/poco/', $contact['url'])];
- DBA::update('contact', $fields, ['id' => $contact['id']]);
- }
-
- $postvars = [];
-
- $sent_dfrn_id = hex2bin((string) $res->dfrn_id);
- $challenge = hex2bin((string) $res->challenge);
-
- $final_dfrn_id = '';
-
- if ($contact['duplex'] && strlen($contact['prvkey'])) {
- openssl_private_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['prvkey']);
- openssl_private_decrypt($challenge, $postvars['challenge'], $contact['prvkey']);