1
0
mirror of https://github.com/nerzhul/ocsms.git synced 2025-06-10 17:36:21 +00:00

Merge branch 'master' of https://github.com/nerzhul/ocsms into stable

This commit is contained in:
Loic Blot 2014-12-29 09:56:18 +00:00
commit 5ab518c9f2
9 changed files with 239 additions and 106 deletions

View File

@ -1,49 +1,58 @@
# Oc Sms
## ownCloud SMS
## Introduction
Oc Sms provides a webinterface to display your SMS conversations.
### Introduction
ownCloud SMS provides a webinterface to display your SMS conversations.
SMS conversations are pushed by your Android devices using ownCloud Sms app, available on Google Play Store
SMS conversations are pushed by your Android devices using ownCloud SMS app, available on Google Play Store.
Android download link: https://play.google.com/store/apps/details?id=fr.unix_experience.owncloud_sms
ownCloud SMS Android App sources are partially available here: https://github.com/nerzhul/ownCloud-SMS-App
## Licence
OcSMS web application is currently under AGPL licence but this free licence can be modificated to a better free licence.
### Licence
ownCloud SMS (OcSMS) web application is currently under AGPL licence but this free licence can be modificated to a better free licence.
## Requirements
### Requirements
- An ownCloud instance
- An Andoid phone
## Installation
Place this app in **owncloud/apps/**
### Installation
1. Download the [latest release](https://github.com/nerzhul/ocsms/releases)
2. Place this app in **owncloud/apps/** and unpack it
3. Activate the app in https://your-owncloud/index.php/settings/apps?installed
4. Download the Android client from [Google Play](https://play.google.com/store/apps/details?id=fr.unix_experience.owncloud_sms)
5. Activate the Android client by adding an account in your phone settings
## ocsms app issues
Please create your issues here:
### Owncloud SMS core issues
*Please create your core issues here:*
https://github.com/nerzhul/ocsms/issues
Server
### Issue template
**Server**
- ownCloud version: X.X.X
- PHP version: X.X
- HTTPd server: <apache|nginx...>
- HTTPS: <yes|no>
Client
**Client**
- Android version: X.X.X
- Phone: <phone-model>
- ownCloud SMS app version: X.X.X
Please also include extract of owncloud.log
**Content of /owncloud/data/owncloud.log**
```
Place content of your owncloud.log here
```
## Android client issues
Please create your issues for the Android client here:
### Android client issues
*Please create your issues for the Android client here:*
https://github.com/nerzhul/ownCloud-SMS-App/issues

View File

@ -29,5 +29,5 @@ namespace OCA\OcSms\AppInfo;
// the title of your application. This will be used in the
// navigation or on the settings page of your app
'name' => \OCP\Util::getL10N('ocsms')->t('Oc Sms')
'name' => \OCP\Util::getL10N('ocsms')->t('SMS')
));

View File

@ -1,8 +1,8 @@
<?xml version="1.0"?>
<info>
<id>ocsms</id>
<name>Oc Sms</name>
<description>Owncloud SMS app</description>
<name>ownCloud SMS</name>
<description>A app to sync SMS with your ownCloud</description>
<licence>AGPL</licence>
<author>Loic Blot</author>
<version>1.3.2</version>

View File

@ -9,6 +9,7 @@
* @copyright Loic Blot 2014
*/
namespace OCA\OcSms\AppInfo;
@ -19,16 +20,20 @@ use \OCA\OcSms\Controller\SmsController;
use \OCA\OcSms\Db\Sms;
use \OCA\OcSms\Db\SmsMapper;
use \OCA\OcSms\Lib\PhoneNumberFormatter;
class OcSmsApp extends App {
/**
* @var array used to cache the parsed contacts for every request
*/
private static $contacts;
private static $contactsInverted;
/*
caching dosn´t work because on every call all will be reinstantiated
*/
private static $contacts; // dosn´t work
private static $contactsInverted; // dosn´t work
private $c;
public function __construct (array $urlParams=array()) {
@ -37,7 +42,7 @@ class OcSmsApp extends App {
$container = $this->getContainer();
$this->c = $container;
$app = $this;
/**
* Controllers
*/
@ -80,22 +85,22 @@ class OcSmsApp extends App {
public function getContacts() {
// Only load contacts if they aren't in the buffer
// dosn´t work
if(count(self::$contacts) == 0) {
$this->loadContacts();
}
return self::$contacts;
}
public function getInvertedContacts() {
// Only load contacts if they aren't in the buffer
// dosn´t work
if(count(self::$contactsInverted) == 0) {
$this->loadContacts();
}
return self::$contactsInverted;
}
/**
* Partially importe this function from owncloud Chat app
* https://github.com/owncloud/chat/blob/master/app/chat.php
@ -103,19 +108,13 @@ class OcSmsApp extends App {
private function loadContacts() {
self::$contacts = array();
self::$contactsInverted = array();
$cm = $this->c['ContactsManager'];
if ($cm == null) {
return;
}
$result = array();
try {
$result = $cm->search('',array('FN'));
} catch (Exception $e) {
// If contact manager failed, avoid the issue
return;
}
$result = $cm->search('',array('FN'));
foreach ($result as $r) {
if (isset ($r["TEL"])) {
@ -133,20 +132,17 @@ class OcSmsApp extends App {
}
}
/*
all numbers will be formatted
*/
private function pushPhoneNumberToCache($rawPhone, $contactName) {
$phoneNb = preg_replace("#[ ]#", "/", $rawPhone);
$phoneNbNoSpaces = preg_replace("#[ ]#", "", $rawPhone);
self::$contacts[$phoneNb] = $contactName;
self::$contacts[$phoneNbNoSpaces] = $contactName;
$phoneNb = PhoneNumberFormatter::format($rawPhone);
self::$contacts[$phoneNb] = $contactName;
// Inverted contacts
if (!isset(self::$contactsInverted[$contactName])) {
self::$contactsInverted[$contactName] = array();
}
array_push(self::$contactsInverted[$contactName], $phoneNb);
if ($phoneNb != $phoneNbNoSpaces) {
array_push(self::$contactsInverted[$contactName], $phoneNbNoSpaces);
}
}
}

View File

@ -19,6 +19,7 @@ $application->registerRoutes($this, array('routes' => array(
array('name' => 'sms#replace', 'url' => '/replace', 'verb' => 'POST'),
array('name' => 'sms#retrieve_all_ids', 'url' => '/get/smsidlist', 'verb' => 'GET'),
array('name' => 'sms#retrieve_all_ids_with_status', 'url' => '/get/smsidstate', 'verb' => 'GET'),
array('name' => 'sms#retrieve_last_timestamp', 'url' => '/get/lastmsgtime', 'verb' => 'GET'),
array('name' => 'sms#retrieve_all_peers', 'url' => '/get/peerlist', 'verb' => 'GET'),
array('name' => 'sms#get_conversation', 'url' => '/get/conversation', 'verb' => 'GET'),
array('name' => 'sms#check_new_messages', 'url' => '/get/new_messages', 'verb' => 'GET'),

View File

@ -18,6 +18,7 @@ use \OCP\AppFramework\Controller;
use \OCP\AppFramework\Http\JSONResponse;
use \OCA\OcSms\AppInfo\OcSmsApp;
use \OCA\OcSms\Db\SmsMapper;
use \OCA\OcSms\Lib\PhoneNumberFormatter;
class SmsController extends Controller {
@ -68,12 +69,31 @@ class SmsController extends Controller {
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* This function is used by API v1
* Phone will compare its own message list with this
* message list and send the missing messages
* This call will remain as secure slow sync mode (1 per hour)
*/
public function retrieveAllIds () {
$smsList = $this->smsMapper->getAllIds($this->userId);
return new JSONResponse(array("smslist" => $smsList));
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* This function is used by API v2
* Phone will get this ID to push recent messages
* This call will be used combined with retrieveAllIds
* but will be used more times
*/
public function retrieveLastTimestamp () {
$ts = $this->smsMapper->getLastTimestamp($this->userId);
return new JSONResponse(array("timestamp" => $ts));
}
/**
* @NoAdminRequired
* @NoCSRFRequired
@ -94,16 +114,18 @@ class SmsController extends Controller {
$countPhone = count($phoneList);
foreach ($phoneList as $number => $ts) {
$fmtPN = preg_replace("#[ ]#","/", $number);
if (isset($contactsSrc[$fmtPN])) {
$fmtPN2 = preg_replace("#\/#","", $fmtPN);
$contacts[$fmtPN] = $contactsSrc[$fmtPN];
$contacts[$fmtPN2] = $contactsSrc[$fmtPN];
$fmtPN = PhoneNumberFormatter::format($number);
if (isset($contactsSrc[$number])) {
$contacts[$number] = $contactsSrc[$number];
} elseif (isset($contactsSrc[$fmtPN])) {
$contacts[$number] = $contactsSrc[$fmtPN];
} elseif (isset($contacts[$fmtPN])) {
$contacts[$number] = $fmtPN;
} else {
$contacts[$number] = $fmtPN;
}
}
$lastRead = $this->smsMapper->getLastReadDate($this->userId);
return new JSONResponse(array("phonelist" => $phoneList, "contacts" => $contacts, "lastRead" => $lastRead));
}
@ -115,9 +137,7 @@ class SmsController extends Controller {
$contacts = $this->app->getContacts();
$iContacts = $this->app->getInvertedContacts();
$contactName = "";
// Add slashes to index properly
$fmtPN = preg_replace("#[ ]#","/", $phoneNumber);
$fmtPN = PhoneNumberFormatter::format($phoneNumber);
if (isset($contacts[$fmtPN])) {
$contactName = $contacts[$fmtPN];
}
@ -125,48 +145,29 @@ class SmsController extends Controller {
$messages = array();
$phoneNumbers = array();
$msgCount = 0;
// This table will be used to avoid duplicates
$noSpacesPhones = array();
// Contact resolved
if ($contactName != "" && isset($iContacts[$contactName])) {
$ctPn = count($iContacts[$contactName]);
// We merge each message list into global messagelist
for ($i=0; $i < $ctPn; $i++) {
// Remove slashes
$fmtPN = preg_replace("#[/]#"," ", $iContacts[$contactName][$i]);
$messages = $messages +
$this->smsMapper->getAllMessagesForPhoneNumber($this->userId, $fmtPN, $lastDate);
$msgCount += $this->smsMapper->countMessagesForPhoneNumber($this->userId, $fmtPN);
$fmtPNNoSpaces = preg_replace("#[ ]#","", $fmtPN);
if (!in_array($fmtPNNoSpaces, $noSpacesPhones)) {
$phoneNumbers[] = $fmtPN;
$noSpacesPhones[] = $fmtPNNoSpaces;
}
// forall numbers in iContacts
foreach($iContacts[$contactName] as $cnumber) {
$messages = $messages + $this->smsMapper->getAllMessagesForPhoneNumber($this->userId, $cnumber, $lastDate);
$msgCount += $this->smsMapper->countMessagesForPhoneNumber($this->userId, $cnumber);
$phoneNumbers[] = PhoneNumberFormatter::format($cnumber);
}
}
else {
// remove slashes
$fmtPN = preg_replace("#[/]#"," ", $phoneNumber);
$messages = $this->smsMapper->getAllMessagesForPhoneNumber($this->userId, $fmtPN, $lastDate);
$msgCount = $this->smsMapper->countMessagesForPhoneNumber($this->userId, $fmtPN);
$fmtPNNoSpaces = preg_replace("#[ ]#","", $fmtPN);
if (!in_array($fmtPNNoSpaces, $noSpacesPhones)) {
$phoneNumbers[] = $fmtPN;
$noSpacesPhones[] = $fmtPNNoSpaces;
$messages = $this->smsMapper->getAllMessagesForPhoneNumber($this->userId, $phoneNumber, $lastDate);
$msgCount = $this->smsMapper->countMessagesForPhoneNumber($this->userId, $phoneNumber);
if(isset($peerNumber[$fmtPN])) {
foreach($peerNumber[$fmtPN] as $cnumber) {
$messages = $messages + $this->smsMapper->getAllMessagesForPhoneNumber($this->userId, $cnumber, $lastDate);
$msgCount += $this->smsMapper->countMessagesForPhoneNumber($this->userId, $cnumber);
}
}
$phoneNumbers[] = PhoneNumberFormatter::format($phoneNumber);
}
// Order by id (date)
ksort($messages);
// Set the last read message for the conversation (all phone numbers)
if (count($messages) > 0) {
$maxDate = max(array_keys($messages));
@ -204,6 +205,7 @@ class SmsController extends Controller {
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function push ($smsCount, $smsDatas) {
if ($this->checkPushStructure($smsCount, $smsDatas, true) === false) {

View File

@ -14,6 +14,8 @@ namespace OCA\OcSms\Db;
use \OCP\IDb;
use \OCP\AppFramework\Db\Mapper;
use \OCA\OcSms\AppInfo\OcSmsApp;
use \OCA\OcSms\Lib\PhoneNumberFormatter;
class SmsMapper extends Mapper {
/*
@ -70,6 +72,18 @@ class SmsMapper extends Mapper {
return $smsList;
}
public function getLastTimestamp ($userId) {
$query = \OCP\DB::prepare('SELECT max(sms_date) as mx FROM ' .
'*PREFIX*ocsms_smsdatas WHERE user_id = ?');
$result = $query->execute(array($userId));
if ($row = $result->fetchRow()) {
return $row["mx"];
}
return 0;
}
public function getAllPeersPhoneNumbers ($userId) {
$query = \OCP\DB::prepare('SELECT sms_address FROM ' .
'*PREFIX*ocsms_smsdatas WHERE user_id = ? AND sms_mailbox IN (?,?)');
@ -77,38 +91,77 @@ class SmsMapper extends Mapper {
$phoneList = array();
while($row = $result->fetchRow()) {
if (!in_array($row["sms_address"], $phoneList)) {
array_push($phoneList, $row["sms_address"]);
$pn = $row["sms_address"];
if (!in_array($pn, $phoneList)) {
array_push($phoneList, $pn);
}
}
return $phoneList;
}
/*
get all possible SMS_adresses for a given formated phonenumber
*/
public function getAllPhoneNumbersForFPN ($userId,$phoneNumber) {
$query = \OCP\DB::prepare('SELECT sms_address FROM ' .
'*PREFIX*ocsms_smsdatas WHERE user_id = ? AND sms_mailbox IN (?,?)');
$result = $query->execute(array($userId, 0, 1));
$phoneList = array();
while($row = $result->fetchRow()) {
$pn = $row["sms_address"];
$fmtPN = PhoneNumberFormatter::format($pn);
if (!isset($phoneList[$fmtPN])) {
$phoneList[$fmtPN] = array();
}
if(!isset($phoneList[$fmtPN][$pn])) {
$phoneList[$fmtPN][$pn] = 0;
}
$phoneList[$fmtPN][$pn] += 1;
}
$fpn = PhoneNumberFormatter::format($phoneNumber);
if(isset($phoneList[$fpn])){
return $phoneList[$fpn];
}
else {
return array();
}
}
public function getAllMessagesForPhoneNumber ($userId, $phoneNumber, $minDate = 0) {
$phlst = $this->getAllPhoneNumbersForFPN ($userId,$phoneNumber);
$messageList = array();
$query = \OCP\DB::prepare('SELECT sms_date, sms_msg, sms_type FROM ' .
'*PREFIX*ocsms_smsdatas WHERE user_id = ? AND sms_address = ? ' .
'AND sms_mailbox IN (?,?) AND sms_date > ?');
$result = $query->execute(array($userId, $phoneNumber, 0, 1, $minDate));
$messageList = array();
while ($row = $result->fetchRow()) {
$messageList[$row["sms_date"]] = array(
"msg" => $row["sms_msg"],
"type" => $row["sms_type"]
);
foreach( $phlst as $pn => $val) {
$result = $query->execute(array($userId, $pn, 0, 1, $minDate));
while ($row = $result->fetchRow()) {
$messageList[$row["sms_date"]] = array(
"msg" => $row["sms_msg"],
"type" => $row["sms_type"]
);
}
}
return $messageList;
}
public function countMessagesForPhoneNumber ($userId, $phoneNumber) {
$cnt = 0;
$phlst = $this->getAllPhoneNumbersForFPN ($userId,$phoneNumber);
$query = \OCP\DB::prepare('SELECT count(sms_date) as ct FROM ' .
'*PREFIX*ocsms_smsdatas WHERE user_id = ? AND sms_address = ? ' .
'AND sms_mailbox IN (?,?)');
$result = $query->execute(array($userId, $phoneNumber, 0, 1));
if ($row = $result->fetchRow()) {
return $row["ct"];
foreach($phlst as $pn => $val) {
$result = $query->execute(array($userId, $pn, 0, 1));
if ($row = $result->fetchRow())
$cnt += $row["ct"];
}
return $cnt;
}
public function getLastMessageTimestampForAllPhonesNumbers ($userId, $order = true) {
@ -125,7 +178,7 @@ class SmsMapper extends Mapper {
$phoneList = array();
while ($row = $result->fetchRow()) {
$phoneNumber = preg_replace("#[ ]#", "/", $row["sms_address"]);
$phoneNumber = $row["sms_address"];
if (!in_array($phoneNumber, $phoneList)) {
$phoneList[$phoneNumber] = $row["mx"];
}
@ -201,14 +254,13 @@ class SmsMapper extends Mapper {
$userId, (int) $sms["_id"]
));
}
$query = \OCP\DB::prepare('INSERT INTO *PREFIX*ocsms_smsdatas ' .
'(user_id, added, lastmodified, sms_flags, sms_date, sms_id,' .
'sms_address, sms_msg, sms_mailbox, sms_type) VALUES ' .
'(?,?,?,?,?,?,?,?,?,?)');
$result = $query->execute(array(
$userId, "NOW()", "NOW()", $smsFlags,
(int) $sms["date"], (int) $sms["_id"],
$sms["date"], (int) $sms["_id"],
$sms["address"], $sms["body"], (int) $sms["mbox"],
(int) $sms["type"]
));

View File

@ -303,6 +303,10 @@ function fetchInitialPeerList(jsondata) {
}
function initDesktopNotifies() {
if (!("Notification" in window)) {
return;
}
Notification.requestPermission(function (permission) {
if(!('permission' in Notification)) {
Notification.permission = permission;

View File

@ -0,0 +1,69 @@
<?php
/**
* ownCloud - ocsms
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Loic Blot <loic.blot@unix-experience.fr>
* @contributor: stagprom <https://github.com/stagprom/>
* @copyright Loic Blot 2014
*/
namespace OCA\OcSms\Lib;
class PhoneNumberFormatter {
public static function format ($pn) {
$ipnrxp = array( // match international numbers with 1,2,3 digits
'#^(00|\+)(1\d\d\d)#', // NANP
'#^(00|\+)(2[1|2|3|4|5|6|8|9]\d)#', // +2(1|2|3|4|5|6|8|9)x
'#^(00|\+)(2[0|7])#', // +2x
'#^(00|\+)(3[5|7|8]\d)#', // +3(5|7|8)x
'#^(00|\+)(3[0|1|2|3|4|6|9])#', // +3x
'#^(00|\+)(4[2]\d)#', // +4(2)x
'#^(00|\+)(4[0|1|3|4|5|6|7|8|9])#', // +4x
'#^(00|\+)(5[0|9]\d)#', // +5(0|9)x
'#^(00|\+)(5[1|2|3|4|5|6|7|8])#', // +5x
'#^(00|\+)(6[7|8|9]\d)#', // +6(7|8|9)x
'#^(00|\+)(6[0|1|2|3|4|5|6])#', // +6x
'#^(00|\+)(7)#', // +7
'#^(00|\+)(8[5|7|8|9]\d)#', // +8(5|7|8|9)x
'#^(00|\+)(8[1|2|3|4|6])#', // +8x
'#^(00|\+)(9[6|7|9]\d)#', // +9(6|7|9)x
'#^(00|\+)(9[0|1|2|3|4|5|8])#' // +9x
);
$ignrxp = array( // match non digits and +
'#[^\d\+\(\)\[\]\{\}]#', // everything but digit, +, (), [] or {}
'#(.+)([\(\[\{]\d*[\)\]\}])#', // braces inside the number: +49 (0) 123 456789
'#[^\d\+]#' // everything but digits and +
);
$ignrpl = array( // replacements
'',
'$1',
''
);
/*
@TODO: make local settings in web-page
*/
$lpnrxp = array( // match local numbers
'#(^0)([^0])#' // in germany : 0-xx[x[x]]-123456
); //
$lpnrpl = '+49$2'; // replace with +49 -xx[x[x]]-123456
$tpn = trim($pn);
if (preg_match('#^[\d\+\(\[\{].*#',$tpn)) { // start with digit, +, (, [ or {
$fpn = preg_replace($ignrxp, $ignrpl, $tpn); // replace everything but digits/+ with ''
$xpn = preg_replace($lpnrxp, $lpnrpl, $fpn); // replace local prenumbers
$ypn = preg_replace($ipnrxp, '+$2', $xpn); // format to international coding +x[x[x]].....
} else {
$ypn = $tpn; // some SMS_adresses are strings
}
return $ypn;
}
};