/* libsswf_tag_protect.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */

/*

Copyright (c) 2002-2008 Made to Order Software Corp.

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

/** \file
 *
 * \brief The implementation of the sswf::TagProtect class
 *
 * This file declares the body of the functions which are not
 * inline. It is part of the SSWF library.
 */

#include	"sswf/libsswf.h"

using namespace sswf;



/////////////////////////////////////////// TagProtect

/** \class sswf::TagProtect
 *
 * \brief Mark the movie as protected
 *
 * The TagProtect object is used to mark a movie as protected against
 * piracy. This is just a tag. The movie itself is not otherwise
 * protected. Macromedia asks that movies marked as protected not be
 * editable by a graphical tool. However, an tool can choose to
 * ignore or not that tag.
 *
 * You should put this tag close to the beginning of the movie.
 *
 * Since version 5, it is possible to add a password in the movie
 * itself. The password is encrypted using some MD5 algorithm.
 * Note that, password or not, the entire movie can still be read
 * anyway!
 *
 * \sa <a href="../SWFalexref.html#tag_protect">SWF Alexis' Reference&mdash;Protect</a>
 * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
 */



/** \brief Initialize the TagProtect object
 *
 * The TagProtect tag marks a movie as protected against piracy...
 * The truth is that this is just a tag. All the other tags remain
 * the same and are not in any way encoded. So the protection holds
 * only if the tools you are using honor that protection. And since
 * many tools in existance already do not (or can be used to remove
 * this tag) that's not very much of a protection.
 *
 * The tag used will depend on the version of the movie being saved.
 *
 *	\li SWF_TAG_PROTECT (up to version 4)
 *	\li SWF_TAG_PROTECT_DEBUG (version 5)
 *	\li SWF_TAG_PROTECT_DEBUG2 (version 6+)
 *
 * \param parent The TagHeader where the TagProtect needs to be created
 */
TagProtect::TagProtect(TagBase *parent)
	: TagBase("protect", parent)
{
	f_password = 0;
}



/** \brief Check the type of the TagProtect tag
 *
 * Defines the generic type of this tag. You should put only one in the
 * whole movie, it should be close to the start of the movie and it is
 * considered as being a control tag.
 *
 * \return Control, Unique and Start
 */
TagBase::swf_type_t TagProtect::TypeFlags(void) const
{
	// here the unicity is a bit particular
	// you can have one PROTECT and
	// one of PROTECT_DEBUG or PROTECT_DEBUG2
	return SWF_TYPE_CONTROL | SWF_TYPE_UNIQUE | SWF_TYPE_START;
}


/** \brief Set a non-encoded password for movie protection
 *
 * This function can be used to define the protection password.
 *
 * In this case the library takes care of the password encoding.
 *
 * \note This function is not yet implemented.
 *
 * \param password A clear text password to protect the movie
 */
void TagProtect::SetPassword(const char *password)
{
	// TODO: we need the MD5 encryption right away so we don't
	//	 keep sensitive strings in memory just like that!
	MemFree(f_password);
	f_password = StrDup(password);
	assert(0, "TODO: protect password encryption not supported yet.\n");
}


/** \brief Set pre-encoded password for movie protection
 *
 * This function can be used to define the protection password.
 *
 * In this case the library takes care of the password encoding.
 *
 * \param password A pre-encoded MD5 password
 */
void TagProtect::SetEncodedPassword(const char *password)
{
	// in this case the caller encoded the password already
	MemFree(f_password);
	f_password = StrDup(password);
}


/** \brief Defines the minimum version required for this tag.
 *
 * The TagProtect object requires a minimum version of 2 unless
 * a password is defined in which case the minimum version is 5.
 */
ErrorManager::error_code_t TagProtect::PreSave(void)
{
	if(f_password == 0) {
		MinimumVersion(2);
	}
	else {
		MinimumVersion(5);
	}

	return ErrorManager::ERROR_CODE_NONE;
}


/** \brief Save the protect tag in a Data buffer
 *
 * Saves the Protect tag in the specified Data buffer.
 *
 * The SWF tag is chosen depending on the version of
 * the movie:
 *
 * 2 to 4 -- SWF_TAG_PROTECT
 *   5    -- SWF_TAG_PROTECT_DEBUG
 *   6+   -- SWF_TAG_PROTECT_DEBUG2
 *
 * \param data A data buffer where the TagProtect is saved
 *
 * \return This function returns 0 on success, non zero otherwise
 */
ErrorManager::error_code_t TagProtect::Save(Data& data)
{
	int		l;
	const char	*password;
	unsigned char	version;

	version = Version();

	if(version < 5) {
		// special case where nothing else than the
		// tag is necessary
		SaveTag(data, SWF_TAG_PROTECT, 0);
		return ErrorManager::ERROR_CODE_NONE;
	}

	if(f_password == 0) {
		// default "no password" for debug tags
		password = "$1$.e$7cXTDev5MooPv3voVnOMX1";
	}
	else {
		password = f_password;
	}

	l = strlen(password) + 1;

	if(version > 5) {
		SaveTag(data, SWF_TAG_PROTECT_DEBUG2, l + 2);
		data.PutShort(0);
	}
	else {
		SaveTag(data, SWF_TAG_PROTECT_DEBUG, l);
	}
	data.Write(password, l);

	return ErrorManager::ERROR_CODE_NONE;
}





/* The following options fold the documentation; use 'zi' to turn on and off
 *
 * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
 */
