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

📄 flickr.cpp

📁 著名的相册网站flickr开发了他的API
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
	cppFlickr

	Copyright (c) 2005, Gareth Simpson (http://www.xurble.org/)
	All rights reserved.

	See License.txt for terms and conditions.
*/

#include "stdafx.h"
#include "Flickr.h"

#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
#include <libxml/nanohttp.h>

#include "iconv.h"

#include <sstream>
#include <vector>
#include <algorithm>

namespace cppFlickr
{
static const char DEFAULT_URL[] = "http://www.flickr.com/services/rest/";

//------------------------------------------------------------------------------------------
//Ctor
Flickr::Flickr()
{
	m_baseURL = DEFAULT_URL;
}
//------------------------------------------------------------------------------------------
//Ctor
Flickr::Flickr(const std::wstring& apikey,const std::wstring& email,const std::wstring& password)
{
	m_baseURL = DEFAULT_URL;
	m_email = urlEncode(makeUTF(email));
	m_password = urlEncode(makeUTF(password));
	m_emailRaw = makeUTF(email);
	m_passwordRaw =makeUTF(password);
	m_apiKey = makeUTF(apikey);

	//	uncomment if using fiddler
	//xmlNanoHTTPScanProxy("http://127.0.0.1:8888/");

}


//------------------------------------------------------------------------------------------
//	Ascii to wide
std::wstring Flickr::makeWide(const std::string& in)
{
	//	TODO: Use iconv here for cross platformness
	std::wstring retStr = L"UTF Conversion Failure"; // TODO: Something better here!
	int len = (int)in.length() + 1;
	if(len > 0)
	{
		wchar_t* wideBuffer = new wchar_t[len+1];
		memset(wideBuffer,0,(sizeof(wchar_t) * (len+1)));
		int ret = MultiByteToWideChar(CP_UTF8,0,in.c_str(),(int)in.length()+1,wideBuffer,len);

		if(ret > 0)
		{
			retStr = wideBuffer;
		}
		delete[] wideBuffer;
	}
	return retStr;
}
//------------------------------------------------------------------------------------------
// convert wide to ascii
std::string Flickr::makeUTF(const std::wstring& str)
{
    int l =static_cast<int>(str.length());
    int sz=::WideCharToMultiByte(CP_UTF8,0,str.c_str(),l,0,0,0,0);

    std::vector<char> buffer;
    buffer.resize(sz);

    ::WideCharToMultiByte(CP_UTF8,0,str.c_str(),l,&buffer[0],sz,0,0);

    return std::string(buffer.begin(),buffer.end());
}

//------------------------------------------------------------------------------------------
//Add a note at the specified co-ordinates
int Flickr::addNote(int photoID,int x,int y, int width, int height, const std::wstring& text,int& retID)
{
	int ret = -1;

	std::stringstream url;
	url << m_baseURL << "?";
	//	 Build the request string
	url << "method=flickr.photos.notes.add&api_key=" << m_apiKey << "&photo_id=" << photoID;

	//	params
	url << "&note_x=" << x << "&note_y=" << y << "&note_w=" << width << "&note_h=" << height << "&note_text=" << urlEncode(makeUTF(text)); 

	//	authentication
	url << "&email=" << m_email << "&password="  << m_password;

	xmlDocPtr doc = (xmlDocPtr)doGet(url.str());
	if(doc)
	{
		// make sure that document is not an error
		ret = checkError(doc);
		if(ret == 0)
		{
			xmlNodePtr root = xmlDocGetRootElement(doc);

			xmlNodePtr idNode = root->xmlChildrenNode->next;	

			xmlChar* id =  xmlGetProp(idNode,(const xmlChar *)"id");
			retID = atoi((const char*)id);
			xmlFree(id);

		}

		
		xmlFreeDoc(doc);

		/*
		*Free the global variables that may
		*have been allocated by the parser.
		*/
		xmlCleanupParser();
	}
	return ret;

}
//------------------------------------------------------------------------------------------
//	Add tags to the photo
int Flickr::addTags(int photoID, const std::wstring& tags)
{
	std::stringstream url;
	url << m_baseURL << "?";
	//	 Build the request string
	url << "method=flickr.photos.addTags&api_key=" << m_apiKey << "&photo_id=" << photoID << "&tags=" << urlEncode(makeUTF(tags));
	//	authentication
	url << "&email=" << m_email << "&password="  << m_password;
	return simpleUpdate(url.str());
}


//------------------------------------------------------------------------------------------
// replace the tags on the photo with a new set
int Flickr::setTags(int photoID, const std::wstring& tags)
{
	std::stringstream url;
	url << m_baseURL << "?";
	//	 Build the request string
	url << "method=flickr.photos.setTags&api_key=" << m_apiKey << "&photo_id=" << photoID << "&tags=" << urlEncode(makeUTF(tags));
	//	authentication
	url << "&email=" << m_email << "&password="  << m_password;
	return simpleUpdate(url.str());
}


//------------------------------------------------------------------------------------------
//	This function will check if the passed in document is a fail response
// if it is, we parse out the error message and response code
int Flickr::checkError(void* doc)
{
	int ret = 0;

	xmlDocPtr xmlDoc = (xmlDocPtr)doc;

	xmlNodePtr root = xmlDocGetRootElement(xmlDoc);

	xmlChar* stat =  xmlGetProp(root,(const xmlChar *)"stat");

	if(xmlStrcmp(stat,(const xmlChar *)"ok"))
	{
		xmlNodePtr codeNode = root->xmlChildrenNode->next;	
		xmlChar* msg =  xmlGetProp(codeNode,(const xmlChar *)"msg");
		xmlChar* code =  xmlGetProp(codeNode,(const xmlChar *)"code");

		m_errorMsg = makeWide((char*)msg);
		ret = atoi((const char*)code);

		if (ret == 0) ret = -2;
		
		xmlFree(msg);
		xmlFree(code);

	}
	else
	{
		//	It was OK!
		m_errorMsg = L"OK";
	}
	xmlFree(stat);

	return ret;
	
}

//------------------------------------------------------------------------------------------
//	performs the passed in get operation and returns the XML result
void* Flickr::doGet(const std::string& url)
{
	xmlDocPtr doc = 0;

	// send it
	void* ctx = xmlNanoHTTPMethod(url.c_str(),"GET",0,0,0,0);
	if(ctx)
	{
		//	some kind of response
		std::stringstream response;

		//	get the XML that is returned
		while(true)
		{
			char buf[1024];
			int read = xmlNanoHTTPRead(ctx,buf,1023);
			if(read > 0)
			{
				buf[read] = 0;
				response << buf;

			}
			if (read < 1023)
				break;
		}
		xmlNanoHTTPClose(ctx);

		//	parse it into a document
		doc = xmlReadMemory(response.str().c_str(),(int)response.str().length(),m_baseURL.c_str(),0, XML_PARSE_NONET );

		if(!doc)
		{
			m_errorMsg = L"Server response was invalid";
		}

	}
	else
	{
		m_errorMsg = L"Could not connect to the server";
	}


	return doc;
}




//------------------------------------------------------------------------------------------
//	Performs simple sets which don't retrieve results
int Flickr::simpleUpdate(const std::string& url)
{
	int ret = -1;
	

	xmlDocPtr doc = (xmlDocPtr)doGet(url);
	if(doc)
	{
		// make sure that document is not an error
		ret = checkError(doc);
		
		xmlFreeDoc(doc);

		/*
		*Free the global variables that may
		*have been allocated by the parser.
		*/
		xmlCleanupParser();
	}

	return ret;
}

//------------------------------------------------------------------------------------------
//	replace with something standard ???
std::string Flickr::urlEncode(const std::string& str)
{
	std::stringstream ret;

	for(size_t i =0; i < str.length(); ++i)
	{
		char c = str[i];
		if((c >= 48 && c <= 57)  ||
			(c >= 65 && c <= 90)  ||
			(c >= 97 && c <= 122))
		{
			ret << c;
		}
		else if(c == 32)
		{
			ret << "+";
		}
		else 
		{
			char buf[5];
			sprintf(buf,"%%%00x",c);
			ret << buf;
		}
	}
	return ret.str();
}

//------------------------------------------------------------------------------------------
//	This is the heart of it

// default jpeg version
int Flickr::uploadFile(const std::wstring& path,const std::wstring& title,const std::wstring& description, const std::wstring& tags, bool isPublic, bool isFriend,bool isFamily,int& retID)
{
	return uploadFile(path,title,description,tags,isPublic,isFriend,isFamily,L"image/jpeg",retID);
}
//	Full on version
int Flickr::uploadFile(const std::wstring& path,const std::wstring& title,const std::wstring& description, const std::wstring& tags, bool isPublic, bool isFriend,bool isFamily,const std::wstring& imgMime, int& retID)
{
	const char targetURL[] = "http://www.flickr.com/tools/uploader_go.gne";
	//const char targetURL[] = "http://www.flickr.com/tools/uploader_test.gne";

	char* contentType = "multipart/form-data; boundary=\"cppFlickrBoundry\"";

	std::stringstream header;

	header << "--cppFlickrBoundry\r\n";
	header << "Content-Disposition: form-data; name=\"email\"\r\n\r\n" << m_emailRaw << "\r\n";

	header << "--cppFlickrBoundry\r\n";
	header << "Content-Disposition: form-data; name=\"password\"\r\n\r\n" << m_passwordRaw << "\r\n";

	if(title.length())
	{
		header << "--cppFlickrBoundry\r\n";
		header << "Content-Disposition: form-data; name=\"title\"\r\n\r\n" << makeUTF(title) << "\r\n";
	}
	if(description.length())
	{

⌨️ 快捷键说明

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