📄 obexftp.cpp
字号:
#include "stdafx.h"
#include "obexFTP.h"
#include <ObexStrings.h>
#include <bt_sdp.h>
#pragma comment(lib,"comsupp.lib")
#pragma comment(lib,"ccrtrtti.lib")
//-----------------------------------------------------------------
// CObexDeviceProperties: ctor(1) with an IPropertyBag *
// useful for OnDeviceXXX functions
//-----------------------------------------------------------------
CObexDeviceProperties::CObexDeviceProperties(IPropertyBag *Prop) : m_Bag(Prop)
{
}
//-----------------------------------------------------------------
// CObexDeviceProperties: ctor(2) with an IObexDevice *
// first query the device for the Properties
//-----------------------------------------------------------------
CObexDeviceProperties::CObexDeviceProperties(IObexDevice *Dev)
{
IPropertyBag *Bag=NULL;
if (Dev && SUCCEEDED(Dev->EnumProperties(__uuidof(IPropertyBag),(void **)&Bag)))
{
m_Bag=Bag;
}
}
//-----------------------------------------------------------------
// CObexDeviceProperties: ctor(3) with an IUnknown *
// used internally in IObexSink::Notify
//-----------------------------------------------------------------
CObexDeviceProperties::CObexDeviceProperties(IUnknown *Unk)
{
CComQIPtr<IPropertyBag> Bag(Unk);
if (Bag)
{
m_Bag=Bag.Detach();
}
}
//-----------------------------------------------------------------
// CObexDeviceProperties: dtor - noop
//-----------------------------------------------------------------
CObexDeviceProperties::~CObexDeviceProperties()
{
}
//-----------------------------------------------------------------
// CObexDeviceProperties: GetProperty
// Basic call to read any property
//-----------------------------------------------------------------
HRESULT CObexDeviceProperties::GetProperty(LPCOLESTR PropName,VARIANT &Value)
{
if (m_Bag)
{
return m_Bag->Read(PropName,&Value,NULL);
}
else
{
return E_FAIL;
}
}
//-----------------------------------------------------------------
// CObexDeviceProperties: GetProperty
// return the string value of a property
//-----------------------------------------------------------------
CString CObexDeviceProperties::GetProperty(LPCOLESTR PropName)
{
CComVariant varValue;;
CString strValue;
if (SUCCEEDED(GetProperty(PropName,varValue)))
{
if (SUCCEEDED(varValue.ChangeType(VT_BSTR)))
{
strValue=varValue.bstrVal;
}
}
return strValue;
}
CString CObexDeviceProperties::GetName() // NAME of the Device
{
return GetProperty(c_szDevicePropName);
}
CString CObexDeviceProperties::GetAddress() // ADDRESS of the device
{
return GetProperty(c_szDevicePropAddress);
}
CString CObexDeviceProperties::GetTransport() // TRANSPORT of the device
{
return GetProperty(c_szDevicePropTransport);
}
CString CObexDeviceProperties::GetServices() // SERVICEs of the device
{
return GetProperty(c_szDeviceServiceUUID);
}
bool CObexDeviceProperties::CanFTP() // OBEX-FTP supported?
{
CString strServ=GetServices();
if (!strServ.IsEmpty())
{
LPCWSTR pszServ=strServ;
for ( ; (pszServ=wcschr(pszServ,L'{'))!=NULL; ++pszServ)
{
UINT uuid16=wcstoul(pszServ+1,NULL,16);
if (uuid16==OBEXFileTransferServiceClassID_UUID16)
return true;
}
}
return false;
}
CStreamToMemory::CStreamToMemory(UINT Initial/*=0*/,UINT Add/*=4096*/)
: m_Buffer(NULL),m_PageSize(Add),m_Allocated(0),m_Filled(0)
{
if (Initial)
{
m_Buffer=(BYTE *)malloc(Initial);
if (m_Buffer) m_Allocated=Initial;
}
}
CStreamToMemory::~CStreamToMemory()
{
Clear();
}
BOOL CStreamToMemory::Read(IStream *pStream)
{
if (pStream==NULL)
{
return FALSE;
}
ULONG cbJustRead,cbSum=0;
BYTE aTempBuffer[1024];
while (SUCCEEDED(pStream->Read(aTempBuffer,1024,&cbJustRead)))
{
if (m_Filled+cbJustRead>=m_Allocated)
{
UINT newAlloc=m_Allocated;
while (m_Filled+cbJustRead>newAlloc)
newAlloc+=m_PageSize;
if (m_Allocated==0) m_Buffer=(BYTE *)malloc(m_Allocated=newAlloc);
else m_Buffer=(BYTE *)realloc(m_Buffer,newAlloc);
if (m_Buffer==NULL) return FALSE;
}
memcpy(m_Buffer+m_Filled,aTempBuffer,cbJustRead);
// Make sure there is a additional zero byte for ascii files
m_Buffer[m_Filled+=cbJustRead]=0;
cbSum+=cbJustRead;
}
return cbSum!=0;
}
UINT CStreamToMemory::Size()
{
return m_Filled;
}
BYTE *CStreamToMemory::GetData()
{
return m_Buffer;
}
void CStreamToMemory::Clear()
{
free(m_Buffer); m_Buffer=NULL;
m_Filled=m_Allocated=0;
}
CObexListing::CObexListing(UINT Initial/*=0*/,UINT Add/*=4096*/)
: CStreamToMemory(Initial,Add),m_pCur(NULL)
{
}
CObexListing::~CObexListing()
{
}
// Format of the obex-filelist date properties
// yyyymmddThhmmssZ
void CObexListing::GetDateProp(const char *p,FILETIME &ft)
{
SYSTEMTIME st;
st.wYear = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + (p[3] - '0');
st.wMonth = 10 * (p[4] - '0') + (p[5] - '0');
st.wDay = 10 * (p[6] - '0') + (p[7] - '0');
st.wHour = 10 * (p[9] - '0') + (p[10] - '0');
st.wMinute = 10 * (p[11] - '0') + (p[12] - '0');
st.wSecond = 10 * (p[13] - '0') + (p[14] - '0');
SystemTimeToFileTime(&st, &ft);
}
// if the text text at current pointer m_pCur matches <t>, advance m_pCur and return true
// otherwise do not touch m_pCur and return false
bool CObexListing::AtText(const char *t)
{
int tl=strlen(t);
if (0==_strnicmp(m_pCur,t,tl))
{
m_pCur+=tl;
return true;
}
return false;
}
// Skip white space
char *CObexListing::Skip(const char *t)
{
while (isspace(*t)) ++t;
return (char *)t;
}
// if the text at the current pointer m_pCur matches <t>, then analyse a
// property as: name = "value"
// if the string is properly formatted then
// point <ppAt> to the fisrst chat of value
// replace the terminating " with NUL
// return true
// Caution: you have to call NextProp to revert the changes!
bool CObexListing::IsProp(const char *t,char **pAt)
{
char *save=m_pCur;
if (AtText(t))
{
char *p=m_pCur; m_pCur=save;
if (isspace(*p)) p=Skip(t);
if (*p++!='=') return false;
p=Skip(p);
if (*p++!='\"') return false;
*pAt=p;
while (*p && *p!='\"') ++p;
if (*p)
{
*(m_pCur=p)=0;
return true;
}
}
return false;
}
// revert the changes made by IsProp and advance
// m_pCur to point to the next property
void CObexListing::NextProp()
{
*m_pCur++='\"';
m_pCur=Skip(m_pCur);
}
// Skip an unknown property
void CObexListing::SkipProp()
{
char *p=strchr(m_pCur,'\"');
if (p)
p=strchr(p+1,'\"');
if (p)
m_pCur=Skip(p+1);
else
m_pCur+=strlen(m_pCur);
}
// assume a well formed obex folder-list
BOOL CObexListing::FindFirstFile(WIN32_FIND_DATA *FindFileData,UINT Mask)
{
m_Mask=Mask&(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_NORMAL);
if (Size()==0 || (m_pCur=(char *)GetData())==NULL)
return FALSE;
m_pCur=strstr(m_pCur,"<folder-listing");
if (m_pCur==NULL)
return FALSE;
else
{
++m_pCur;
if (m_Mask&FILE_ATTRIBUTE_DIRECTORY)
{
// Is there are parent folder available
char *parent=strstr(m_pCur,"<parent-folder");
if (parent)
{
memset(FindFileData,0,sizeof(WIN32_FIND_DATA));
wcscpy(FindFileData->cFileName,L"..");
FindFileData->dwFileAttributes=FILE_ATTRIBUTE_DIRECTORY;
return true;
}
}
return FindNextFile(FindFileData);
}
}
BOOL CObexListing::FindNextFile(WIN32_FIND_DATA *FindFileData)
{
while (1)
{
if (m_pCur==NULL || (m_pCur=strstr(m_pCur,"<f"))==NULL)
return FALSE;
memset(FindFileData,0,sizeof(WIN32_FIND_DATA));
if (AtText("<folder "))
FindFileData->dwFileAttributes=FILE_ATTRIBUTE_DIRECTORY;
else if (AtText("<file "))
FindFileData->dwFileAttributes=FILE_ATTRIBUTE_NORMAL;
else
{
m_pCur=NULL;
return FALSE;
}
char *PropAt=strstr(m_pCur,"/>");
if (PropAt==NULL)
{
m_pCur=NULL;
return FALSE;
}
if ((FindFileData->dwFileAttributes&m_Mask)==0)
{
// not interested in this kind of oject: file/folder
m_pCur=Skip(PropAt+2);
}
else
{
// interpret the properties
*PropAt=0;
UINT dateFlags=0;
while (*m_pCur)
{
if (IsProp("name",&PropAt))
{
MultiByteToWideChar (CP_ACP, 0, PropAt, -1, FindFileData->cFileName, MAX_PATH);
NextProp();
}
else if (IsProp("size",&PropAt))
{
FindFileData->nFileSizeLow=atoi(PropAt);
NextProp();
}
else if (IsProp("created",&PropAt))
{
GetDateProp(PropAt,FindFileData->ftCreationTime);
dateFlags|=1;
NextProp();
}
else if (IsProp("modified",&PropAt))
{
GetDateProp(PropAt,FindFileData->ftLastWriteTime);
dateFlags|=2;
NextProp();
}
else if (IsProp("accessed",&PropAt))
{
GetDateProp(PropAt,FindFileData->ftLastAccessTime);
dateFlags|=4;
NextProp();
}
else
{
SkipProp();
}
}
*m_pCur++='/'; m_pCur++;
if (dateFlags && dateFlags!=7)
{
if ((dateFlags&1)==0)
{
if (dateFlags&2) FindFileData->ftCreationTime=FindFileData->ftLastWriteTime;
else FindFileData->ftCreationTime=FindFileData->ftLastAccessTime;
}
if ((dateFlags&2)==0)
{
if (dateFlags&1) FindFileData->ftLastWriteTime=FindFileData->ftCreationTime;
else FindFileData->ftLastWriteTime=FindFileData->ftLastAccessTime;
}
if ((dateFlags&4)==0)
{
if (dateFlags&2) FindFileData->ftLastAccessTime=FindFileData->ftLastWriteTime;
else FindFileData->ftLastAccessTime=FindFileData->ftCreationTime;
}
}
return TRUE;
}
}
}
BOOL CObexListing::FindClose()
{
Clear();
return TRUE;
}
//-------------------------------------------------------------------
// CObexFTP ctor - call Initialize after construction !
//-------------------------------------------------------------------
CObexFTP::CObexFTP() : m_cRef(1),m_bEnumerating(false)
{
}
//-------------------------------------------------------------------
// CObexFTP dtor - stop enumeration, relaese connection point, and
// shutdown IObex
//-------------------------------------------------------------------
CObexFTP::~CObexFTP()
{
// close all active connections
CObexFTPConnection *c;
while ((c=m_Connections.m_pHead)!=NULL)
{
c->Disconnect();
}
if (m_obex)
{
StopDeviceEnumeration();
m_obex->Shutdown();
m_obex=NULL;
}
}
//-------------------------------------------------------------------
// CObexFTP::Initialize - call after ctor to init the obex system
//-------------------------------------------------------------------
BOOL CObexFTP::Initialize()
{
// already initialzed ?
if (m_obex)
{
return TRUE;
}
else
{
// CoCreate an instance of IObex
m_obex.CoCreateInstance(__uuidof(Obex));
if (m_obex)
{
// Call IObex::Initialize
if (SUCCEEDED(m_obex->Initialize()))
{
// Advise the IObexSink connection point
LPUNKNOWN pUnkThis;
QueryInterface(IID_IUnknown,(void **)&pUnkThis);
m_dwAdvise=0;
if (SUCCEEDED(AtlAdvise(m_obex,pUnkThis,IID_IObexSink,&m_dwAdvise)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -