Skip to content

Instantly share code, notes, and snippets.

@Voyager2718
Created October 28, 2015 11:47
Show Gist options
  • Save Voyager2718/9e995c469fc7f28cef53 to your computer and use it in GitHub Desktop.
Save Voyager2718/9e995c469fc7f28cef53 to your computer and use it in GitHub Desktop.
Fixed the bug that may cause problem while adding friend.
<?xml version="1.0" encoding="UTF-8"?>
<component name="dataSourceStorage">
<data-source name="MySQL - IM@localhost" uuid="a946eda0-b4af-45ad-a268-cc18a9119e97">
<database-info product="MySQL" version="5.5.5-10.0.17-MariaDB" jdbc-version="4.0" driver-name="MySQL Connector Java" driver-version="mysql-connector-java-5.1.35 ( Revision: 5fb9c5849535c13917c2cf9baaece6ef9693ef27 )">
<extra-name-characters>#@</extra-name-characters>
<identifier-quote-string>`</identifier-quote-string>
</database-info>
<case-sensitivity plain-identifiers="lower" quoted-identifiers="lower"/>
<schema name="" catalog="im"/>
<table name="friends" schema="" catalog="im" type="TABLE">
<column name="FriendID" sqlType="INT" precision="10" scale="0" nullable="false" jdbcType="4" autoIncrement="true"/>
<column name="UID_A" sqlType="INT" precision="10" scale="0" nullable="false" jdbcType="4"/>
<column name="UID_B" sqlType="INT" precision="10" scale="0" nullable="false" jdbcType="4"/>
<column name="AIsFriendOfB" sqlType="TINYINT" precision="3" scale="0" nullable="false" jdbcType="-6" def="MQ=="/>
<column name="BIsFriendOfA" sqlType="TINYINT" precision="3" scale="0" nullable="false" jdbcType="-6" def="MA=="/>
<column name="RootPasswordOfA" sqlType="TEXT" precision="65535" scale="0" nullable="false" jdbcType="-1" remarks="VGhpcyBwYXNzd29yZCBzaG91bGQgYmUgZW5jcnlwdGVkIGJ5IHRoZSByb290IHBhc3N3b3JkIG9mIEEgYW5kIHdvbid0IGJlIGNoYW5nZWQgZm9yZXZlci4="/>
<column name="RootPasswordOfB" sqlType="TEXT" precision="65535" scale="0" nullable="false" jdbcType="-1" remarks="VGhpcyBwYXNzd29yZCBzaG91bGQgYmUgZW5jcnlwdGVkIGJ5IHRoZSByb290IHBhc3N3b3JkIG9mIEIgYW5kIHdvbid0IGJlIGNoYW5nZWQgZm9yZXZlci4="/>
<column name="RequestAdding" sqlType="TINYINT" precision="3" scale="0" nullable="false" jdbcType="-6" def="MQ=="/>
<column name="PrivateKey" sqlType="TEXT" precision="65535" scale="0" nullable="false" jdbcType="-1" remarks="VGhpcyBwcml2YXRlIGtleSBzaG91bGQgYmUgZW5jcnlwdGVkIGJ5IHRoZSByb290IHBhc3N3b3JkIG9mIEEu"/>
<column name="PublicKey" sqlType="TEXT" precision="65535" scale="0" nullable="false" jdbcType="-1"/>
<primary-key name="PRIMARY" columns="FriendID"/>
</table>
<table name="messages" schema="" catalog="im" type="TABLE">
<column name="MessageID" sqlType="INT" precision="10" scale="0" nullable="false" jdbcType="4" autoIncrement="true"/>
<column name="FromUID" sqlType="INT" precision="10" scale="0" nullable="false" jdbcType="4"/>
<column name="ToUID" sqlType="INT" precision="10" scale="0" nullable="false" jdbcType="4"/>
<column name="Message" sqlType="TEXT" precision="65535" scale="0" nullable="false" jdbcType="-1"/>
<column name="SentTime" sqlType="TIMESTAMP" precision="19" scale="0" nullable="false" jdbcType="93" def="Q1VSUkVOVF9USU1FU1RBTVA=" version="true"/>
<column name="AlreadyRead" sqlType="TINYINT" precision="3" scale="0" nullable="false" jdbcType="-6" def="MA=="/>
<primary-key name="PRIMARY" columns="MessageID"/>
</table>
<table name="users" schema="" catalog="im" type="TABLE">
<column name="UserID" sqlType="INT" precision="10" scale="0" nullable="false" jdbcType="4" autoIncrement="true"/>
<column name="Alias" sqlType="CHAR" precision="32" scale="0" nullable="false" jdbcType="1"/>
<column name="JoinedTime" sqlType="TIMESTAMP" precision="19" scale="0" nullable="false" jdbcType="93" def="Q1VSUkVOVF9USU1FU1RBTVA=" version="true"/>
<column name="Password" sqlType="CHAR" precision="32" scale="0" nullable="false" jdbcType="1"/>
<column name="RootPassword" sqlType="TEXT" precision="65535" scale="0" nullable="false" jdbcType="-1" remarks="VGhpcyBwYXNzd29yZCBzaG91bGQgYmUgZW5jcnlwdGVkIGJ5IHVzZXIgcGFzc3dvcmQgYW5kIHJlbmV3IHdoZW4gY2hhbmdpbmcgdXNlciBwYXNzd29yZC4="/>
<primary-key name="PRIMARY" columns="UserID"/>
</table>
</data-source>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" hash="3667147382">
<data-source source="LOCAL" name="MySQL - IM@localhost" uuid="a946eda0-b4af-45ad-a268-cc18a9119e97">
<driver-ref>mysql</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306/IM</jdbc-url>
<driver-properties>
<property name="zeroDateTimeBehavior" value="convertToNull" />
<property name="tinyInt1isBit" value="false" />
<property name="characterEncoding" value="utf8" />
<property name="characterSetResults" value="utf8" />
<property name="yearIsDateType" value="false" />
</driver-properties>
<libraries />
</data-source>
</component>
</project>
<component name="ProjectDictionaryState">
<dictionary name="YANG">
<words>
<w>dbname</w>
</words>
</dictionary>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/IM.iml" filepath="$PROJECT_DIR$/.idea/IM.iml" />
</modules>
</component>
</project>
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$" dialect="MySQL" />
</component>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:47
*/
class ChatController
{
protected $chatModel;
protected $friendsModel;
function __construct()
{
$this->chatModel = new ChatModel();
$this->friendsModel = new FriendsModel();
}
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 27-Oct-15
* Time: 23:55
*/
class AlreadyInFriendshipException extends Exception
{
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:47
*/
class FriendsController
{
protected $friendModel;
protected $UID;
function __construct($UID)
{
$this->friendModel = new FriendsModel();
$this->UID = $UID;
}
/**
* @param $UID
* @param $privateKey : This key should be encrypted by the root password of A.
* @param $publicKey : This key should be generated by private key.
* @throws AlreadyInFriendshipException
*/
public function addFriend($UID, $privateKey, $publicKey)
{
if ($this->friendModel->isMutualFriend($this->UID, $UID)) //If A B are already friends.
throw new AlreadyInFriendshipException("You're already a friend with him.");
if ($this->friendModel->getBIsFriendOfA($UID, $this->UID)) { //If B is a friend of A, then they have friendship directly.
$this->friendModel->setAIsFriendOfB($this->UID, $UID, true);
return;
}
if ($this->friendModel->getAIsFriendOfB($this->UID, $UID)) { //If A is a friend of B, then nothing will be changed but send a request.
$this->friendModel->setRequestAdding($UID, true);
return;
}
$this->friendModel->addFriend($this->UID, $UID, $privateKey, $publicKey); //If A B have no friendship, then do things as normal.
}
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:53
*/
class UserController
{
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:48
*/
class ChatDrawer implements Drawer
{
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:28
*/
interface Drawer
{
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:49
*/
class FriendsDrawer implements Drawer
{
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:50
*/
class UserDrawer implements Drawer
{
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:32
*/
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:50
*/
class ChatModel
{
protected $DB; //This is a PDO Object.
/**
* This constructor will initialize the PDO Object
*/
function __construct()
{
$DBMS = 'mysql'; //Type of database
$host = "localhost"; //Address of database
$DBName = "IM"; //Name of database
$DBUsername = "root"; //Username of database
$DBPassword = ""; //Password of database
$DSN = "$DBMS:host=$host;dbname=$DBName";
try {
$this->DB = new PDO($DSN, $DBUsername, $DBPassword);
$query = $this->DB->prepare("SET NAMES UTF8;");
$query->execute();
} catch (PDOException $e) {
throw $e;
}
}
/**
* @param $UID_A
* @param $UID_B
* @return mixed : If A and B used to have message, return true, else raise a NoConversationException:.
* @throws NoConversationException If A and B used to have message, return true, else raise a NoConversationException.
*/
public function getHaveMessage($UID_A, $UID_B)
{
$query = $this->DB->prepare("SELECT `MessageID` FROM `messages`
WHERE (`FromUID` = '%s' AND `ToUID` = '%s') OR (`FromUID` = '%s' AND `ToUID` = '%s');");
$array = $query->execute(array($UID_A, $UID_B, $UID_B, $UID_A));
if (!$array)
throw new NoConversationException();
true;
}
/**
* @param $fromUID
* @param $toUID
* @param $message : Message should be encrypted by the root password of this friendship.
* Before creating message, should verify if two users are friends.
*/
public function createMessage($fromUID, $toUID, $message)
{
$query = $this->DB->prepare("INSERT INTO `messages` (`FromUID`, `ToUID`, `Message`) VALUES ('%s','%s','%s');");
$query->execute(array($fromUID, $toUID, $message));
}
/**
* @param $toUID
* @return mixed : Return encrypted messages(MessageID, FromUID, ToUID, Message, SentTime, AlreadyRead).
*/
public function getUnreadMessages($toUID)
{
$query = $this->DB->prepare("SELECT * FROM `messages` WHERE `ToUID` = '%s' AND `AlreadyRead` = 0 ORDER BY SentTime DESC;");
$array = $query->execute(array($toUID));
return $array;
}
/**
* @param $UID_A
* @param $UID_B
* @return mixed : Return encrypted messages(MessageID, FromUID, ToUID, Message, SentTime, AlreadyRead).
*/
public function getMessages($UID_A, $UID_B)
{
$query = $this->DB->prepare("SELECT * FROM `messages`
WHERE (`FromUID` = '%s' AND `ToUID` = '%s') OR (`FromUID` = '%s' AND `ToUID` = '%s') ORDER BY SentTime DESC;");
$array = $query->execute(array($UID_A, $UID_B, $UID_A, $UID_B));
return $array;
}
/**
* @param $messageID : Only receiver can indicate that a message has been read.
* @param $bool : The value that will be set to AlreadyRead.
*/
public function setAlreadyRead($messageID, $bool)
{
$query = $this->DB->prepare("UPDATE `messages` SET `AlreadyRead` = '%s' WHERE `MessageID` = '%s';");
$query->execute(array($bool, $messageID));
}
/**
* @param $messageID
* @return mixed : Return the sent time of a message.
*/
public function getSentTime($messageID)
{
$query = $this->DB->prepare("SELECT `SentTime` FROM `messages` WHERE `MessageID` = '%s';");
$array = $query->execute(array($messageID));
return $array['SentTime'];
}
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 27-Oct-15
* Time: 17:04
*/
class NoResultException extends Exception
{
}
class NotInFriendshipException extends Exception
{
}
class NoConversationException extends Exception
{
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:50
*/
class FriendsModel
{
protected $DB; //This is a PDO Object.
/**
* This constructor will initialize the PDO Object
*/
function __construct()
{
$DBMS = 'mysql'; //Type of database
$host = "localhost"; //Address of database
$DBName = "IM"; //Name of database
$DBUsername = "root"; //Username of database
$DBPassword = ""; //Password of database
$DSN = "$DBMS:host=$host;dbname=$DBName";
try {
$this->DB = new PDO($DSN, $DBUsername, $DBPassword);
$query = $this->DB->prepare("SET NAMES UTF8;");
$query->execute();
} catch (PDOException $e) {
throw $e;
}
}
/**
* @param $UID_A
* @param $UID_B
* @return mixed : If at least one user is friend of another user, return their FriendID, else return false.
*/
public function isFriend($UID_A, $UID_B)
{
$query = $this->DB->prepare("SELECT `FriendID` FROM `friends` WHERE (`UID_A` = '%s' AND `UID_B` = '%s') OR (`UID_A` = '%s' AND `UID_B` = '%s');");
$array = $query->execute(array($UID_A, $UID_B, $UID_B, $UID_A));
if (!$array)
return false;
return true;
}
/**
* @param $UID_A
* @param $UID_B
* @return mixed : If at least one user is friend of another user, return their FriendID, else return false.
*/
public function isMutualFriend($UID_A, $UID_B)
{
$query = $this->DB->prepare("SELECT `FriendID` FROM `friends` WHERE ((`UID_A` = '%s' AND `UID_B` = '%s') OR (`UID_A` = '%s' AND `UID_B` = '%s')) AND `AIsFriendOfB` = 1 AND `BIsFriendOfA` = 1;");
$array = $query->execute(array($UID_A, $UID_B, $UID_B, $UID_A));
if (!$array)
return false;
return true;
}
/**
* @param $UID_A
* @param $UID_B
* @return mixed : If at least one user is friend of another user, return their FriendID, else raise a NotInFriendshipException.
* @throws NotInFriendshipException If at least one user is friend of another user, return their FriendID, else raise a NotInFriendshipException.
*/
public function getFriendID($UID_A, $UID_B)
{
$query = $this->DB->prepare("SELECT `FriendID` FROM `friends` WHERE (`UID_A` = '%s' AND `UID_B` = '%s') OR (`UID_A` = '%s' AND `UID_B` = '%s');");
$array = $query->execute(array($UID_A, $UID_B, $UID_B, $UID_A));
if (!$array)
throw new NotInFriendshipException();
return $array['FriendID'];
}
/**
* @param $UID_A
* @param $UID_B
* And this password should be encrypt by root password of A.
* And this password should be encrypt by root password of B.
* @param $privateKey : This key will be used to exchange root password of this friendship and should be encrypted by
* the root password of A.
* @param $publicKey : This key will be used to exchange root password of this friendship and should be encrypted by
* the root password of A.
*/
public function addFriend($UID_A, $UID_B, $privateKey, $publicKey)
{
$query = $this->DB->prepare("INSERT INTO `friends` (`UID_A`, `UID_B`,`PrivateKey`,`PublicKey`)
VALUES('%s', '%s', '%s','%s');");
$query->execute(array($UID_A, $UID_B, $privateKey, $publicKey));
}
/**
* @param $UID_B
* @return mixed : Return a list are requesting B to add them as friend.
*/
public function getRequestAdding($UID_B)
{
$query = $this->DB->prepare("SELECT `UID_A` FROM `friends` WHERE `UID_B` = '%s' AND `RequestAdding` = 1;");
$array = $query->execute(array($UID_B));
return $array['UID_A'];
}
public function setRequestAdding($UID_B, $bool)
{
$query = $this->DB->prepare("UPDATE `friends` SET `RequestAdding` = '%s' WHERE `FriendID` = '%s';");
$query->execute(array($bool, $UID_B));
}
/**
* @param $friendID
* @param $rootPasswordOfA : Set the root password of A(This password should be encrypted by root password of A).
*/
public function setRootPasswordOfA($friendID, $rootPasswordOfA)
{
$query = $this->DB->prepare("UPDATE `friends` SET `RootPasswordOfA` = '%s' WHERE `FriendID` = '%s';");
$query->execute(array($friendID, $rootPasswordOfA));
}
/**
* @param $friendID
* @param $rootPasswordOfB : Set the root password of B(This password should be encrypted by root password of A).
*/
public function setRootPasswordOfB($friendID, $rootPasswordOfB)
{
$query = $this->DB->prepare("UPDATE `friends` SET `RootPasswordOfB` = '%s' WHERE `FriendID` = '%s';");
$query->execute(array($friendID, $rootPasswordOfB));
}
/**
* @param $friendID
* @return mixed : Will return the root password of A.
*/
public function getRootPasswordOfA($friendID)
{
$query = $this->DB->prepare("SELECT `RootPasswordOfA` FROM `friends` WHERE `FriendID` = '%s';");
$array = $query->execute(array($friendID));
return $array['RootPasswordOfA'];
}
/**
* @param $friendID
* @return mixed : Will return the root password of A.
*/
public function getRootPasswordOfB($friendID)
{
$query = $this->DB->prepare("SELECT `RootPasswordOfB` FROM `friends` WHERE `FriendID` = '%s';");
$array = $query->execute(array($friendID));
return $array['RootPasswordOfB'];
}
/**
* @param $friendID
* @return mixed : Return the private key.
*/
public function getPrivateKey($friendID)
{
$query = $this->DB->prepare("SELECT `PrivateKey` FROM `friends` WHERE `FriendID` = '%s'");
$array = $query->execute(array($friendID));
return $array['PrivateKey'];
}
/**
* @param $friendID
* @return mixed : Return the public key.
*/
public function setPublicKey($friendID)
{
$query = $this->DB->prepare("SELECT `PublicKey` FROM `friends` WHERE `FriendID` = '%s'");
$array = $query->execute(array($friendID));
return $array['PublicKey'];
}
/**
* @param $UID_A
* @param $UID_B
* @return bool : If UID_A is a friend of UID_B, return true, else false;
* Check if UID_A is a friend of UID_B(Not irreversible, because there's a situation that UID_B is a friend of UID_A, but UID_A
* is not a friend of UID_B).
*/
public function getAIsFriendOfB($UID_A, $UID_B)
{
$query = $this->DB->prepare("SELECT * FROM friends WHERE (`UID_A` = '%s' AND `UID_B` = '%s' AND `AIsFriendOfB` = 1) OR (`UID_B` = '%s' AND `UID_A` = '%s' AND `AIsFriendOfB` = 1);");
$array = $query->execute(array($UID_A, $UID_B, $UID_A, $UID_B));
if ($array)
return true;
return false;
}
/**
* @param $UID_A
* @param $UID_B
* @return bool : If UID_B is a friend of UID_A, return true, else false;
* Check if UID_B is a friend of UID_A(Not irreversible, because there's a situation that UID_B is a friend of UID_A, but UID_A
* is not a friend of UID_B).
*/
public function getBIsFriendOfA($UID_B, $UID_A)
{
$query = $this->DB->prepare("SELECT * FROM friends WHERE (`UID_A` = '%s' AND `UID_B` = '%s' AND `BIsFriendOfA` = 1) OR (`UID_B` = '%s' AND `UID_A` = '%s' AND `BIsFriendOfA` = 1);");
$array = $query->execute(array($UID_A, $UID_B));
if ($array)
return true;
return false;
}
/**
* @param $UID_A
* @param $UID_B
* @param $bool : True means in friend list of A, there's B. On the contrary, in friend list of A, there is not B.
*/
public function setAIsFriendOfB($UID_A, $UID_B, $bool)
{
$query = $this->DB->prepare("UPDATE `friends` SET `AIsFriendOfB` = '%s' WHERE `UID_A` = '%s' AND `UID_B` = '%s';");
$query->execute(array($bool, $UID_A, $UID_B));
}
/**
* @param $UID_A
* @param $UID_B
* @param $bool : True means in friend list of B, there's A. On the contrary, in friend list of B, there is not A.
*/
public function setBIsFriendOfA($UID_B, $UID_A, $bool)
{
$query = $this->DB->prepare("UPDATE `friends` SET `BIsFriendOfA` = '%s' WHERE `UID_A` = '%s' AND `UID_B` = '%s';");
$query->execute(array($bool, $UID_A, $UID_B));
}
}
<?php
/**
* Created by PhpStorm.
* User: YANG
* Date: 25-Oct-15
* Time: 11:50
*/
class UserModel
{
protected $DB; //This is a PDO Object.
/**
* This constructor will initialize the PDO Object
*/
function __construct()
{
$DBMS = 'mysql'; //Type of database
$host = "localhost"; //Address of database
$DBName = "IM"; //Name of database
$DBUsername = "root"; //Username of database
$DBPassword = ""; //Password of database
$DSN = "$DBMS:host=$host;dbname=$DBName";
try {
$this->DB = new PDO($DSN, $DBUsername, $DBPassword);
$query = $this->DB->prepare("SET NAMES UTF8;");
$query->execute();
} catch (PDOException $e) {
throw $e;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment