⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mobilecontrol.cpp

📁 基于vc++6.0的收发手机短信、读写手机电话本的平台
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	BOOL bInternationalMobileNO = TRUE;
	ENUM_ERROR_TYPE eErrorType = ENUM_ERROR_TYPE_SUCCESS;
	if ( ENUM_ERROR_TYPE_SUCCESS != StandardMobileNO ( csReceiverMobileNO, &bInternationalMobileNO ) )
	{
		Log ( L_WARNING, _T("Standard MobileNO failed") );
	}

	// 发送短信前做分条处理
	ASSERT ( szSMSContent_Byte && strlen(szSMSContent_Byte) > 0 );

	CStringArray *pAryStr = PartMessengerOrSMSText ( GetCompatibleString(szSMSContent_Byte,FALSE), 0, TRUE, NULL, NULL );
	if ( !pAryStr ) return ENUM_ERROR_TYPE_PARAMETER;

	for ( int i=0; i<pAryStr->GetSize(); i++ )
	{
		CString csTextOne = pAryStr->GetAt ( i );
		csTextOne.TrimLeft(); csTextOne.TrimRight();
		ENUM_ERROR_TYPE eErrorTypeTemp = SendOnePartSMS ( eMobileSMSType, csReceiverMobileNO, bInternationalMobileNO, 
			CMultiByteString(csTextOne).GetBuffer(), dwSMSSenderID_Sender, Proc_SendSMSEnd, wParam, lParam );
		if ( eErrorTypeTemp != ENUM_ERROR_TYPE_SUCCESS )
		{
			eErrorType = eErrorTypeTemp;
		}
	}
	pAryStr->RemoveAll();
	delete pAryStr;
	return eErrorType;
}

ENUM_ERROR_TYPE CMobileControl::InfillSMParam ( 
		OUT SM_PARAM &SmParam,
		IN CString csReceiverMobileNO	// 接收者手机号
	)
{
	memset ( &SmParam, 0, sizeof(SM_PARAM) );
	if ( !m_nInitOK ) return ENUM_ERROR_TYPE_NoneMobile;
	GetSMSCNO ();
	if ( m_csSMSC.GetLength() <= MIN_MOBILENO_LENGTH )
	{
		Log ( L_ERROR, _T("SMSC Error, Cancel send SMS to [%s]"), csReceiverMobileNO  );
		return ENUM_ERROR_TYPE_ConfigNotRight;
	}
	CString csSMSC = m_csSMSC;
	// 填充短消息结构
	StandardMobileNOHead ( csSMSC );
	CMultiByteString ( csSMSC, STRING_IS_SOFTCODE, SmParam.SCA, sizeof(SmParam.SCA) );
	CMultiByteString ( csReceiverMobileNO, STRING_IS_SOFTCODE, SmParam.TPA, sizeof(SmParam.TPA) );
	SmParam.TP_PID = 0;

	return ENUM_ERROR_TYPE_SUCCESS;
}
//
// 发送短信,过长的短信,这个模块不会处理,请在调用前先处理
//
ENUM_ERROR_TYPE CMobileControl::SendOnePartSMS (
		ENUM_MOBILESMSTYPE eMobileSMSType,
		LPCTSTR lpszReceiverMobileNO,					// 接收者手机号
		BOOL bInternationalMobileNO,
		char* szSMSContent_Byte,						// 单字节短信内容
		DWORD dwSMSSenderID_Sender/*=INVALID_SMSSenderID*/,	// 发送者的 PM 号码
		FUNC_SendSMSEnd Proc_SendSMSEnd/*=NULL*/,		// 发送完成时通过该回调函数来通知请求者
		WPARAM wParam/*=NULL*/,
		LPARAM lParam/*=NULL*/
)
{
	if ( !szSMSContent_Byte || strlen(szSMSContent_Byte) <= 0 )
		return ENUM_ERROR_TYPE_INVALID_DATA;

	// 完全相同(短信内容和接收者手机号相同)的短信在 SAME_SMS_INTERVAL_TIMELONG 秒内不允许发送
	// 防止短信炸弹,也防止 UDP 通信时收到重发的短信包
#ifndef _DEBUG
	static CString csReceiverMobileNO_Last, csSMSContent_Last;
	static time_t tTimeLast = 0;
	if ( csReceiverMobileNO_Last == lpszReceiverMobileNO &&
		csSMSContent_Last == szSMSContent_Byte )
	{
		if ( difftime ( time(NULL), tTimeLast ) < SAME_SMS_INTERVAL_TIMELONG )
		{
			return ENUM_ERROR_TYPE_RepeatedRequest;
		}
	}
	csReceiverMobileNO_Last = GET_SAFE_STRING ( lpszReceiverMobileNO );
	csSMSContent_Last = GET_SAFE_STRING ( szSMSContent_Byte );
	tTimeLast = time(NULL);
#endif

	// 队列是否满了?
	m_CSFor_SMSSendQueue.Lock ();
	if ( m_Ary_SMS_SendQueue.GetSize() > MAX_SMSQUEUE_NUM )
	{
		m_CSFor_SMSSendQueue.Unlock ();
		return ENUM_ERROR_TYPE_BufferQueueFill;
	}
	m_CSFor_SMSSendQueue.Unlock ();

	// 创建一个队列节点
	t_SMS_SendQueue SMS_SendQueue;
	memset ( &SMS_SendQueue, 0, sizeof(t_SMS_SendQueue) );
	SMS_SendQueue.dwSMSSenderID_Sender = dwSMSSenderID_Sender;
	SMS_SendQueue.Proc_SendSMSEnd = Proc_SendSMSEnd;
	SMS_SendQueue.wParam = wParam;
	SMS_SendQueue.lParam = lParam;
	SMS_SendQueue.eMobileSMSType = eMobileSMSType;
	ENUM_ERROR_TYPE eErrorType = InfillSMParam ( SMS_SendQueue.sm, GET_SAFE_STRING(lpszReceiverMobileNO) );
	
	strncpy ( SMS_SendQueue.sm.TP_UD_Byte, szSMSContent_Byte, COUNT(SMS_SendQueue.sm.TP_UD_Byte) );
	SMS_SendQueue.sm.bInternationalMobileNO = bInternationalMobileNO;

	if ( eErrorType != ENUM_ERROR_TYPE_SUCCESS )
		return eErrorType;

	// 做服务器运行时,将要发送的短信包添加到队列中
	BOOL bRes = TRUE;
	if ( m_bRunAsServer )
	{
		m_CSFor_SMSSendQueue.Lock ();
		m_Ary_SMS_SendQueue.Add ( SMS_SendQueue );
		m_CSFor_SMSSendQueue.Unlock ();
		
		// 然后通知手机工作线程
		ASSERT ( m_hEvt_SMSSendQueue && m_hEvt_SMSSendQueue != INVALID_HANDLE_VALUE );
		::SetEvent ( m_hEvt_SMSSendQueue );
	}
	// 单机版时直接发送短信
	else
	{
		bRes = SendOneSMSQueue ( SMS_SendQueue );
	}

	return ( bRes ? ENUM_ERROR_TYPE_SUCCESS : ENUM_ERROR_TYPE_SendSMSFailed );
}

//
// 发送短信队列里的短信
//
BOOL CMobileControl::SendSMSQueue ()
{
	ASSERT ( m_bRunAsServer );
	// 发送队列里的一条短消息
	m_CSFor_SMSSendQueue.Lock ();
	if ( m_Ary_SMS_SendQueue.GetSize() <= 0 )
	{
		m_CSFor_SMSSendQueue.Unlock ();
		return TRUE;
	}
	t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 );
	t_SMS_SendQueue SMS_SendQueue;
	memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) );
	m_Ary_SMS_SendQueue.RemoveAt ( 0 );
	m_CSFor_SMSSendQueue.Unlock ();
	
	BOOL bRes = SendOneSMSQueue ( SMS_SendQueue );
	
	// 系统要退出了
	if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
		return TRUE;
	else
	{
		m_CSFor_SMSSendQueue.Lock ();
		// 还有短信需要发送
		if ( m_Ary_SMS_SendQueue.GetSize() > 0 )
		{
			::SetEvent ( m_hEvt_SMSSendQueue );
		}
		m_CSFor_SMSSendQueue.Unlock ();
	}

	return TRUE;
}

BOOL CMobileControl::AppTextToSMSContent ( SM_PARAM &sm, LPCTSTR lpszAppText, int &nFreeCharNum, BOOL bAddToHead )
{
	ASSERT ( lpszAppText );
	int nAppTextTotalCharNum = 0;
	ParseSMSContentAttr ( CMultiByteString(lpszAppText).GetBuffer(), &nAppTextTotalCharNum );
	if ( nAppTextTotalCharNum < nFreeCharNum )
	{
		CString csTD_UD_Byte = GetCompatibleString(sm.TP_UD_Byte,FALSE);
		if ( bAddToHead ) csTD_UD_Byte.Insert ( 0, lpszAppText );
		else csTD_UD_Byte += lpszAppText;
		CMultiByteString ( csTD_UD_Byte, STRING_IS_SOFTCODE, sm.TP_UD_Byte, sizeof(sm.TP_UD_Byte) );
		nFreeCharNum -= nAppTextTotalCharNum;
		return TRUE;
	}

	return FALSE;
}


BOOL CMobileControl::SendOneSMSQueue ( t_SMS_SendQueue &SMS_SendQueue )
{
	ASSERT ( m_nInitOK );
	ASSERT ( m_pMobileParameter );
	ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE );
	// 系统要退出了
	if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
	{
		if ( SMS_SendQueue.Proc_SendSMSEnd )
		{
			SMS_SendQueue.Proc_SendSMSEnd ( ENUM_ERROR_TYPE_SysTerminate,
				&SMS_SendQueue.sm, SMS_SendQueue.wParam, SMS_SendQueue.lParam );
		}
		return FALSE;
	}

	int nTotalCharNum = 0, nFreeCharNum = 0, nTP_DCS = 0;
	int nOneSMSByteCount = ParseSMSContentAttr ( SMS_SendQueue.sm.TP_UD_Byte,
		&nTotalCharNum, &nFreeCharNum, &nTP_DCS );
	SMS_SendQueue.sm.TP_DCS = nTP_DCS;
	ASSERT ( nFreeCharNum >= 0 );
	CString csSMSContent;

	// 发送以“#howa!#”开头的短信,不附加短信头和尾
	if ( strstr(SMS_SendQueue.sm.TP_UD_Byte,"#howa!#") == SMS_SendQueue.sm.TP_UD_Byte )
	{
		Log ( L_VERBOSE, _T("Not append SMS head and tail") );
		char TP_UD_Byte_Temp[ONE_SMS_TEXT_LENGTH+1] = {0};
		memset ( SMS_SendQueue.sm.TP_UD_Byte, 0, sizeof(SMS_SendQueue.sm.TP_UD_Byte) );
		strcpy ( TP_UD_Byte_Temp, &SMS_SendQueue.sm.TP_UD_Byte[7] );
		strcpy ( SMS_SendQueue.sm.TP_UD_Byte, TP_UD_Byte_Temp );
		csSMSContent = GetCompatibleString(SMS_SendQueue.sm.TP_UD_Byte,FALSE);
	}
	// 附加短信“#760815# [短信内容] Sent by "callgle" ”
	else
	{
		csSMSContent = GetCompatibleString(SMS_SendQueue.sm.TP_UD_Byte,FALSE);
		if ( AppTextToSMSContent ( SMS_SendQueue.sm, m_csSMSTail, nFreeCharNum, FALSE ) )
		{
			AppTextToSMSContent ( SMS_SendQueue.sm, m_csSMSHead, nFreeCharNum, TRUE );
		}
	}

	BOOL bRet = FALSE;
	CStringArray StrAry_MobileNO;
	ASSERT ( m_pMobileParameter );
	bRet = SendOneSMSPkt ( &(SMS_SendQueue.sm) );
	StrAry_MobileNO.Add ( SimplifyMobileNO(GetCompatibleString(SMS_SendQueue.sm.TPA,FALSE)) );

	if ( SMS_SendQueue.Proc_SendSMSEnd )
	{
		SMS_SendQueue.Proc_SendSMSEnd ( bRet?ENUM_ERROR_TYPE_SUCCESS:ENUM_ERROR_TYPE_SendSMSFailed, 
			&(SMS_SendQueue.sm), SMS_SendQueue.wParam, SMS_SendQueue.lParam );
	}
	if ( bRet && m_pdwSentSMSCount )
	{
		(*m_pdwSentSMSCount) ++;
	}
	// 将发送完的短信保存到数据库
	for ( int i=0; i<StrAry_MobileNO.GetSize(); i++ )
	{
	/*	m_pHwMysql_PMMsg->SaveSMSToHistoryRecord (
			SMS_SendQueue.dwSMSSenderID_Sender,
			StrAry_MobileNO.GetAt(i),
			SMS_SendQueue.eMobileSMSType,
			ENUM_SMSOrientation_Send,
			(bRet?ENUM_BOOL_TRUE:ENUM_BOOL_FALSE),
			NULL,
			csSMSContent );*/	//u
	}

	return bRet;
}

void CMobileControl::ClearSendQueue ()
{
	// 还有短信需要发送
	while ( TRUE )
	{
		m_CSFor_SMSSendQueue.Lock ();
		if ( m_Ary_SMS_SendQueue.GetSize() <= 0 )
		{
			m_CSFor_SMSSendQueue.Unlock ();
			break;
		}
		
		t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 );
		t_SMS_SendQueue SMS_SendQueue;
		memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) );
		m_Ary_SMS_SendQueue.RemoveAt ( 0 );
		m_CSFor_SMSSendQueue.Unlock ();

		SendOneSMSQueue ( SMS_SendQueue );
	}
}

BOOL CMobileControl::HandleRecvSMS(SM_PARAM *pSMRecv)
{
	ASSERT ( pSMRecv );
	if ( GetMobileStatus() == ENUM_ERROR_TYPE_MobileDisable )
	{
		Log ( L_WARNING, _T("Discard recevied SMS [%s : %s], because Mobile mobule disable"),
			GetCompatibleString(pSMRecv->TPA,FALSE), GetCompatibleString(pSMRecv->TP_UD_Byte,FALSE) );
		return FALSE;
	}

	if ( !CHwMobile::HandleRecvSMS ( pSMRecv ) )
		return FALSE;

	CString csTemp = SimplifyMobileNO ( GetCompatibleString(pSMRecv->TPA,FALSE) );
	CMultiByteString ( csTemp, STRING_IS_SOFTCODE, pSMRecv->TPA, sizeof(pSMRecv->TPA) );
	ASSERT ( m_Proc_ReceivedSMS );
	return m_Proc_ReceivedSMS ( pSMRecv, m_wParam, m_lParam );
}

//
// 读最新收到的短信
//
BOOL CMobileControl::ReadNewSMS ()
{
	if ( !m_bRecvSMSEnable ) return TRUE;
	if ( HANDLE_IS_VALID(m_hEvt_IsBusy) &&
		::WaitForSingleObject(m_hEvt_IsBusy,0)==WAIT_OBJECT_0 )
		return TRUE;

	ASSERT ( m_nInitOK );
	// 系统要退出了
	if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
		return TRUE;

	ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE );
	if ( !QueryDeviceExist () )
	{
		return FALSE;
	}

	// 收短信通知
	return gsmReadMessageContent ( "+CMT:" );
}

//
// 读取手机中已经存在的所有短信
//
BOOL CMobileControl::ReadExistSMSInMobile()
{
	if ( !m_bRecvSMSEnable ) return TRUE;
	if ( Write ( "AT+CMGL=4\r" ) < 1 )
		return FALSE;
	if ( !WaitForDataToRead ( 2, 5*WAIT_DATA_TIMEOUT ) )
		return FALSE;
	return gsmReadMessageContent ( "+CMGL:" );
}

//
// 读取手机所有电话本。
// 注意:及时删除返回的指针
//
t_Ary_PhoneBook* CMobileControl::ReadPhoneBook()
{
	t_Ary_PhoneBook *pAry_PhoneBook = new t_Ary_PhoneBook;
	if ( !pAry_PhoneBook )
	{
		::AfxThrowMemoryException ();
		return NULL;
	}
	pAry_PhoneBook->SetSize ( 0, 10*sizeof(t_PhoneBook) );

	if ( !gsmReadPhoneBook ( _T("SM"), pAry_PhoneBook ) )
		return pAry_PhoneBook;
	if ( !gsmReadPhoneBook ( _T("ME"), pAry_PhoneBook ) )
		return pAry_PhoneBook;

	return pAry_PhoneBook;
}

LPCTSTR CMobileControl::GetObjectName()
{
	return _T("Mobile control module");
}

//
// 检测字符串 lpszStr 的是否以字符串 lpszHead1 或 lpszHead2 或 lpszHead3 开头
//
LPCTSTR CMobileControl::CheckHeadStr ( LPCTSTR lpszStr, LPCTSTR lpszHead1, LPCTSTR lpszHead2, LPCTSTR lpszHead3 )
{
	if ( !lpszStr || !lpszHead1 || lstrlen(lpszStr) <= 0 )
		return NULL;
	if ( strstr_hw ( lpszStr, lpszHead1 ) == lpszStr )
		return lpszHead1;
	if ( lpszHead2 && strstr_hw ( lpszStr, lpszHead2 ) == lpszStr )
		return lpszHead2;
	if ( lpszHead3 && strstr_hw ( lpszStr, lpszHead3 ) == lpszStr )
		return lpszHead3;

	return NULL;
}

//
// 根据 Callgle 手机短信协议解析收到的短信
// return : -----------------------------------------------------------
//		1											:	成功
//		其他数据									:	发生错误
//		-2											:	在本函数处理已经结束,不需要再处理
// 注意:
//		要及时删除 *ppStrAry_GroupName_Recver 和 *ppStrAry_SMSSenderID_Recver 指针
//
int CMobileControl::ParseSMSRecved ( 
		IN LPCTSTR lpszSMSContent,
		IN LPCTSTR lpszSenderMobileNO,
		OUT CStringArray **ppStrAry_GroupName_Recver,
		// 接收短信者名字或PM帐号,如果是输入控制命令时,这里存放了操作指令和控制命令
		OUT CStringArray **ppStrAry_SMSSenderID_Recver,
		OUT TCHAR *tchSMSContent,
		int nSMSContentSize,
		BOOL &bRequireEchoSMS,
		LPCTSTR lpszSendTime
	)
{
	m_csPartString = _T("");
	bRequireEchoSMS = FALSE;
	// 无效的短信内容,所以我也返回一个无效的消息类型
	if ( !lpszSMSContent || lstrlen(lpszSMSContent) < 2 )
		return -1;

	int nRet = -1;
	ENUM_MOBILESMSTYPE eMobileSMSType = ENUM_MOBILESMSTYPE_Invalid;
	CString csSMSContent = GET_SAFE_STRING ( lpszSMSContent );
	CString csSMSContent_Org = csSMSContent;
	BOOL bMultiSplitSMS = FALSE;
	// 以三个'?'开头的短信表示该短信是分多次发送过来的,需要将前面的三个'?'去掉
	if ( csSMSContent.GetLength() > 3 && csSMSContent.GetAt(0)=='?' &&
		csSMSContent.GetAt(1)=='?' && csSMSContent.GetAt(2)=='?' )
	{
		bMultiSplitSMS = TRUE;
		while ( !csSMSContent.IsEmpty() && csSMSContent.GetAt(0) == '?' )
			csSMSContent.Delete ( 0, 1 );
		csSMSContent_Org = csSMSContent;
		if ( !m_csMultiSplitSMSHead.IsEmpty() && !CheckHeadStr ( csSMSContent, _T("#"), _T("#"), _T("…") ) )
			csSMSContent.Insert ( 0, m_csMultiSplitSMSHead );
	}
	else
	{
		m_csMultiSplitSMSHead = "";
	}
	
	// 非普通短信,而是一个控制命令,处理后的控制命令保存在 “tchSMSContent” 中
	LPCTSTR pStr = CheckHeadStr ( csSMSContent, _T("%"), _T("%"), _T("

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -