Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A C++ Embedded Web Server

, 23 Jun 2014
Give a C++ application its own web page
webem_demo.zip
code_project
examples
webemCalendar
calendar.dat
sqlite3.dll
webemCalendar.vcproj.CORVIS.james.user
webemHello
webemHello.vcproj.CORVIS.james.user
webemHelloForm
webemHelloForm.vcproj.CORVIS.james.user
webemMT
webemMT.vcproj.CORVIS.james.user
src
sqlite
sqlite3.lib
webem
server
Jamfile
Jamfile.v2
webem_src.zip
doc
DoxyFile
html
doxygen.png
tab_b.gif
tab_l.gif
tab_r.gif
examples
webemButton
webemCalendar
calendar.dat
sqlite3.dll
sqlite3.lib
WebemHello
webemHelloForm
server
 /* 
 * Copyright (c) 2008 by James Bremner
 * All rights reserved.
 *
 * Use license: Modified from standard BSD license.
 * 
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation, advertising 
 * materials, Web server pages, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by James Bremner. The name "James Bremner" may not be used to 
 * endorse or promote products derived from this software without 
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */


#include "stdafx.h"
#include "cWebem.h"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <libs/asio/example/http/server/reply.hpp>
#include <libs/asio/example/http/server/request.hpp>

namespace http {
	namespace server {

	typedef std::multimap  < std::string, std::string> webem_mmp_name_value;
	typedef std::multimap  < std::string, std::string>::iterator webem_iter_name_value;

/**

Webem constructor

@param[in] address  e.g. "0.0.0.0"
@param[in] port     e.g. "8080"
@param[in[ doc_root path to folder containing html e.g. "./"

*/
cWebem::cWebem( 
	   const std::string& address,
	   const std::string& port,
	   const std::string& doc_root ) :
myRequestHandler( doc_root ),
myServer( address, port, myRequestHandler )
{
	myRequestHandler.setWebem( this );
}


	/**

	Create a link between a string ID and a function to calculate the dynamic content of the string

	@param[in] idname  string identifier
  @param[in] fun pointer to function which calculates the string to be displayed

*/

void cWebem::RegisterIncludeCode( const char* idname, webem_include_function fun )
{
	myIncludes.insert( std::pair<std::string, webem_include_function >( std::string(idname), fun  ) );
}

void cWebem::RegisterActionCode( const char* idname, webem_action_function fun )
{
	myActions.insert( std::pair<std::string, webem_action_function >( std::string(idname), fun  ) );
}

/**

  Include generated text

  @param[in/out] reply  text to include generated

  The text is searched for "<!--#cWebemX-->".  
  The X can be any string not containing "-->"
  If X has been registered with cWebem them the associated function
  is called to generate text to be inserted.

*/
void cWebem::Include( std::string& reply )
{
	int p = 0;
	while( 1 ) {
		// find next request for generated text
		p = reply.find("<!--#webem",p);
		if( p == -1 ) {
			break;
		}
		int q = reply.find("-->",p);
		if( q == -1 )
			break;;
		q += 3;

		int reply_len = reply.length();

		// code identifying text generator
		std::string code = reply.substr( p+11, q-p-15 );

		// find the function associated with this code
		std::map < std::string, webem_include_function >::iterator pf = myIncludes.find( code );
		if( pf != myIncludes.end() )
			// insert generated text
			reply.insert( p, pf->second() );

		// adjust pointer into text for insertion
		p = q + reply.length() - reply_len;
	}
}
/**

Is this a request from a button clicked on a form with a cWebem action

*/
void cWebem::CheckForAction( std::string& uri )
{
	// look for cWebem form action request
	int q = uri.find(".webem?");
	if( q == -1 )
		return;

	// find function matching action code
	std::string code = uri.substr(1,q-1);
	std::map < std::string, webem_action_function >::iterator
		pfun = myActions.find(  code );
	if( pfun == myActions.end() )
		return;

	// decode the values
	
	myNameValues.clear();
	std::string name;
	std::string value;

	int p = q + 7;
	int flag_done = 0;
	while( ! flag_done ) {
		q = uri.find("=",p);
		name = uri.substr(p,q-p);
		p = q + 1;
		q = uri.find("&",p);
		if( q != -1 )
			value = uri.substr(p,q-p);
		else {
			value = uri.substr(p);
			flag_done = 1;
		}
		// the browser sends blanks as +
		while( 1 ) {
			int p = value.find("+");
			if( p == -1 )
				break;
			value.replace( p, 1, " " );
		}

		myNameValues.insert( std::pair< std::string,std::string > ( name, value ) );
		p = q+1;
	}

	// call the function
	uri = pfun->second( this );

	return;
}
/**

  Find the value of a name set by a form submit action

*/
std::string& cWebem::FindValue( const char* name )
{
	static string ret;
	webem_iter_name_value iter = myNameValues.find( name );
	if( iter != myNameValues.end() )
		ret = iter->second;
	
	return ret;
}

void cWebemRequestHandler::handle_request( const request& req, reply& rep)
{
	// check for webem action request
	request req_modified = req;
	myWebem->CheckForAction( req_modified.uri );

	// do normal handling
	request_handler::handle_request( req_modified, rep);

	// Find and include any special cWebem strings
	myWebem->Include( rep.content );

	// adjust content length header
	// ( Firefox ignores this, but apparently some browsers truncate display without it.
	// fix provided by http://www.codeproject.com/Members/jaeheung72 )

	rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());

}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The BSD License

About the Author

ravenspoint
Founder Raven's Point Consulting
Canada Canada
No Biography provided

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 23 Jun 2014
Article Copyright 2008 by ravenspoint
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid