/** @file JCLayaUrl.cpp @brief @author hugao @version 1.0 @date 2016_5_12 */ #include "JCLayaUrl.h" #include "Log.h" #include "JCCommonMethod.h" namespace laya{ JCUrl::JCUrl(){ m_pszUrl = NULL; m_nProto = unk; m_nUrlSize = 0; m_bHasDriver=false; } JCUrl::JCUrl(const char* p_pszUrl) { m_pszUrl = NULL; m_nProto = unk; m_nUrlSize = 0; m_bHasDriver = false; parse(p_pszUrl); } JCUrl::~JCUrl(){ if(m_pszUrl){ delete [] m_pszUrl; m_pszUrl = NULL; } } void JCUrl::trim(const char*& p_pszData){ char cv = *p_pszData; while(cv==' '||cv=='\t'){ cv=*(++p_pszData); } } //由于js的location是没有 // 所以这个也不要带 // const char* JCUrl::getProtocolString(){ switch (m_nProto) { case laya::JCUrl::http: return "http:"; break; case laya::JCUrl::https: return "https:"; break; case laya::JCUrl::ftp: return "ftp:"; break; case laya::JCUrl::file: return "file:"; break; default: return "unk:"; break; } } //TODO 现在还没有拆分 # std::vector JCUrl::split(const char* p_pszData){ const char* pData = p_pszData; char cv = *pData; std::vector ret; while(cv){ if(cv=='/'||cv=='\\' ){ ret.push_back(pData-p_pszData); }else if(cv=='?'){ ret.push_back(pData-p_pszData); break; } cv = *(++pData); } return ret; } void JCUrl::parseScheme(const char*& p_pszData){ const char* pcur = p_pszData; if((pcur[0]=='h'||pcur[0]=='H')&&(pcur[1]=='t'||pcur[1]=='T')&&(pcur[2]=='t'||pcur[2]=='T')&&(pcur[3]=='p'||pcur[3]=='P')){ if(pcur[4]=='s' || pcur[4]=='S'){ m_nProto = https; p_pszData+=5; }else{ m_nProto = http; //m_Protocol.st=0; m_Protocol.len=4; p_pszData+=4; } }else if((pcur[0]=='f'||pcur[0]=='F')&&(pcur[1]=='t'||pcur[1]=='T')&&(pcur[2]=='p'||pcur[2]=='P')){ m_nProto = ftp; //m_Protocol.st=0; m_Protocol.len=3; p_pszData+=3; }else if((pcur[0]=='f'||pcur[0]=='F')&&(pcur[1]=='i'||pcur[1]=='I')&&(pcur[2]=='l'||pcur[2]=='L')&&(pcur[3]=='e'||pcur[0]=='E')){ //m_Protocol.st=0; m_Protocol.len=4; m_nProto = file; p_pszData+=4; }else{ throw 11; } if(*(p_pszData++)==':' && *(p_pszData++)=='/' && *(p_pszData++)=='/' ){} else throw 12; } void JCUrl::parseUserPassHostPort(const char* p_pszData){ const char* pColonPos=NULL; const char* pAtPos=NULL; const char* pCurData = p_pszData; while(true ){ if(*pCurData==0){ m_Host=pAtPos?(pAtPos):p_pszData; break; } if(*pCurData==':'){ pColonPos=pCurData+1; if(pAtPos){//已经有@了,表示这是端口了 m_Host = ""; m_Host.append(pAtPos,pCurData-pAtPos); m_Port = pColonPos; break; } }else if(*pCurData=='@'){//有用户信息 pAtPos = pCurData+1; if(pColonPos){ m_User="";m_User.append(p_pszData,pColonPos-p_pszData-1); m_Pass="";m_Pass.append(pColonPos, pCurData-pColonPos); }else{ m_User="";m_User.append(p_pszData, pCurData-p_pszData); } } pCurData++; } } void JCUrl::parsePath(const char* pData){ m_vPath.clear(); int datalen = strlen(pData); std::vector parts = split(pData); if( parts.size()>0){ //第一部分 std::string cpath=""; cpath.append(pData,parts[0]); if(cpath!=".") m_vPath.push_back(cpath); bool bHasQuery=false; if(pData[parts[parts.size()-1]]=='?'){//query bHasQuery=true; int nQuerySt =parts[parts.size()-1]; m_Query="";m_Query.append(pData+nQuerySt,datalen-nQuerySt); } //中间 for( int i=0,sz=parts.size()-1; i0){ //if( m_vPath[nPathNum-1].length()==0) //最后一个是文件 //TODO url可能最后是一个目录么?如果是的话怎么处理。按理说应该必须是一个文件。实际的目录自动加index.html是服务器端做得? m_strPath.append(m_vPath[0].c_str()); for(int i=1; i parts = split(pData); if (parts.size() > 0) { //host //m_Host.st=0; m_Host.len=0; //m_Query.st=0; m_Query.len=0; if (parts[0] > 0) {//user,pass,host,port std::string uphp; uphp.append(pData, parts[0]); m_strProtHost.append(pData, parts[0]); parseUserPassHostPort(uphp.c_str()); } bool bHasQuery = false; int lastPos = parts[parts.size() - 1]; if (pData[lastPos] == '?') {//query bHasQuery = true; //m_Query.st=nQuerySt; //m_Query.len=datalen-nQuerySt; //m_Path.st = parts[0];//包含 / //m_Path.len = parts[parts.size()-1]-m_Path.st; m_Query = ""; m_Query.append(pData + lastPos, datalen - lastPos); } else { //m_Path.st = parts[0]; //m_Path.len = datalen-m_Path.st; } for (int i = 0, sz = parts.size() - 1; i < sz; i++) { std::string cpath = ""; int l = (parts[i + 1] - parts[i]) - 1; if (l <= 0 && i != 0 && i != sz - 1) { continue; //空的,通常是 //或者\\或者 /\什么的 } cpath.append((char*)(pData + parts[i] + 1), l); if (cpath == "..") { if (m_vPath.size()) m_vPath.pop_back(); continue; } if (cpath != ".") m_vPath.push_back(cpath); } if (!bHasQuery) { std::string cpath = ""; cpath.append((char*)(pData + parts[parts.size() - 1] + 1), datalen - parts[parts.size() - 1] - 1); if (cpath == "..") { if (m_vPath.size()) m_vPath.pop_back(); } else if (cpath != ".") m_vPath.push_back(cpath); } if (m_vPath.size() > 0 && m_vPath[0].length() > 1 && m_vPath[0][1] == ':') { m_bHasDriver = true; } } else { m_strProtHost = p_pszUrl; parseUserPassHostPort(pData); } //合并path pathToString(false); if(m_strPath.length()>0){ if(m_strPath[0]=='/'){ m_strPath = m_strProtHost+m_strPath; }else{ m_strPath = m_strProtHost+"/"+m_strPath; } }else{ if(m_nProto==file) m_strPath = "file:///"; else m_strPath = m_strProtHost; } }catch(int e){ LOGE("JCUrl::parse error [%d]:%s",e, p_pszUrl ); return false; } return true; } std::string JCUrl::resolve(const char* p_pszPath){ if(strstr(p_pszPath,"://")){ JCUrl pathurl; pathurl.parse(p_pszPath); if(pathurl.m_vPath.size()==1&&pathurl.m_Host.length()<=0) return pathurl.m_strPath+pathurl.m_vPath[pathurl.m_vPath.size()-1]+pathurl.m_Query; //file:///a.txt return pathurl.m_strPath+"/"+ (pathurl.m_vPath.size() > 0 ? pathurl.m_vPath[pathurl.m_vPath.size()-1] : "")+pathurl.m_Query; //file:///a/a.txt } JCUrl pathurl; pathurl.parsePath(p_pszPath); if( pathurl.m_vPath.size()>0){ pathurl.pathToString(true); if(pathurl.m_vPath[0]=="" ){ //绝对路径 if(m_bHasDriver){ return m_strProtHost+"/"+m_vPath[0]+pathurl.m_strPath+pathurl.m_Query; }else return m_strProtHost+pathurl.m_strPath+pathurl.m_Query; }else if(pathurl.m_vPath[0].length()>1&&pathurl.m_vPath[0].at(1)==':'){//带盘符的 return m_strProtHost+"/"+pathurl.m_strPath+pathurl.m_Query; }else{ return m_strPath+"/"+pathurl.m_strPath+pathurl.m_Query; } } return m_strPath; } std::string JCUrl::toString(){ std::string ret = m_strPath +"/"+ (m_vPath.size()>0?m_vPath[m_vPath.size()-1]:"")+m_Query; return ret; } std::string JCUrl::encode2() { if (m_nProto == file || m_vPath.size()<=0) { return toString(); } std::string ret = m_strPath + "/" + UrlEncode(m_vPath[m_vPath.size() - 1].c_str()); if (m_Query.length() > 0) { ret += "?"; ret += UrlEncode(m_Query.substr(1, m_Query.length() - 1).c_str()); } return ret; } }; //------------------------------------------------------------------------------ //-----------------------------END FILE--------------------------------