Esempio n. 1
0
OP_STATUS OpFolderListing::GenerateData()
{
#ifdef _LOCALHOST_SUPPORT_
	// Prefix for local files
# ifdef HAS_COMPLEX_GLOBALS
	static const uni_char * const localhost_prefix =
		UNI_L("file://localhost/");
# else
#  define localhost_prefix UNI_L("file://localhost/")
# endif
	static const size_t localhost_prefix_len = 17;
	OP_ASSERT(uni_strlen(localhost_prefix) == localhost_prefix_len);
#endif

	const uni_char * OP_MEMORY_VAR dirend_char = UNI_L("");
#if PATHSEPCHAR != '/'
	const uni_char * OP_MEMORY_VAR displayable_dirend_char = dirend_char;
#else
# define displayable_dirend_char dirend_char
#endif

	// FIXME: OOM - not reported, not checked

	// Set attributes.
	m_url.SetAttribute(URL::KIsDirectoryListing, TRUE);

	// Get the URL and take copies of it for processing.
	OpString base;
	RETURN_IF_ERROR(m_url.GetAttribute(URL::KUniName_Username_Escaped, base));
	m_temp_base = SetNewStr(base.CStr());
	m_displayable_base_url = SetNewStr(base.CStr());
	if (!m_temp_base || !m_displayable_base_url)
	{
		return OpStatus::ERR_NO_MEMORY;
	}

	// Check if this is a local file or not.
#ifdef _LOCALHOST_SUPPORT_
	OP_MEMORY_VAR bool is_local_file = false;
#else
	static const bool is_local_file = false;
#endif
#ifdef _LOCALHOST_SUPPORT_
	if (uni_strncmp(m_displayable_base_url, localhost_prefix, localhost_prefix_len) == 0)
	{
		is_local_file = true;
	}
#endif

	static const uni_char pathsepchar = '/';

	//  If wildchars, remove upto last PATHSEPCHAR/
	unsigned int PathLen = uni_strcspn(m_temp_base, UNI_L(WILDCHARS));
	if (PathLen != uni_strlen(m_temp_base))
	{
		int i;
		for (i = PathLen; i > 0 && m_temp_base[i] != PATHSEPCHAR && m_temp_base[i] != '/' && m_temp_base[i] != '\\' ; i--) {}
		m_temp_base[i] = '\0';
	}

	PathLen = uni_strcspn(m_temp_base,UNI_L("?"));
	m_temp_base[PathLen] = '\0';
	{
		// Ignore parameter portion, but only for the last element to ensure
		// proper path names for FTP and file (anyone using parameters in the
		// parent directories will just have to take their chances).
		uni_char *temp_path = uni_strrchr(m_temp_base, '/'); // don't bother looking for backslash
		if(temp_path)
		{
			uni_char *temp_param = uni_strchr(temp_path, ';');
			if(temp_param)
			{
				PathLen = temp_param - m_temp_base;
				m_temp_base[PathLen] = '\0';
			}
		}
	}

	// If the path does not end in a path separator, add one.
	if (m_temp_base[PathLen-1] != '/'
#if PATHSEPCHAR != '/'
		&& m_temp_base[PathLen-1] != PATHSEPCHAR
#endif
	   )
	{
		dirend_char = UNI_L("/");
#if PATHSEPCHAR != '/'
		if (is_local_file)
		{
			displayable_dirend_char = UNI_L(PATHSEP);
		}
		else
		{
			displayable_dirend_char = dirend_char;
		}
#endif
	}

	// Create a HTML version of the URL string.
	m_htmlified_url = HTMLify_string(m_temp_base);
	if (!m_htmlified_url)
	{
		return OpStatus::ERR_NO_MEMORY;
	}

	// Transmogrify the URL to make it displayable.
	UriUnescape::ReplaceChars(m_displayable_base_url,
		(static_cast<URLType>(m_url.GetAttribute(URL::KType)) == URL_FILE ?
		 UriUnescape::LocalfileUrlUtf8 : UriUnescape::SafeUtf8));

	// Remove localhost prefix
	if (is_local_file)
		op_memmove(m_displayable_base_url, m_displayable_base_url + localhost_prefix_len, UNICODE_SIZE(uni_strlen(m_displayable_base_url + localhost_prefix_len) + 1));

#ifdef SYS_CAP_FILESYSTEM_HAS_DRIVES
	// Clean up the generated path string
	if (is_local_file)
	{
		// Replace Netscape-compatible "|" as drive letter postfix with
		// a drive separator, which we assume to be ":"
		if (m_displayable_base_url[0] &&
		    '|' == m_displayable_base_url[1])
		{
			m_displayable_base_url[1] = ':';
		}

		// Make sure drive letter is upper-cased
		if (Unicode::IsLower(m_displayable_base_url[0]))
		{
			m_displayable_base_url[0] = Unicode::ToUpper(m_displayable_base_url[0]);
		}
	}
#endif

	// Remove formatting characters
	RemoveFormattingCharacters(m_displayable_base_url);

	// Create a HTML version of the displayable URL string.
	m_htmlified_displayable_base_url = HTMLify_string(m_displayable_base_url);
	if (!m_htmlified_displayable_base_url)
	{
		return OpStatus::ERR_NO_MEMORY;
	}

	// Set up the document title from the displayable URL string.
	OpString document_title;
#ifndef SYS_CAP_FILESYSTEM_HAS_DRIVES
	if (is_local_file)
	{
		// Include an initial slash for local files on file systems that do
		// not have drive letters, to avoid blank titles or titles like
		// "usr/bin".
		if (uni_strcmp(m_htmlified_displayable_base_url, localhost_prefix) == 0)
		{
			RETURN_IF_ERROR(document_title.Set("/"));
		}
		else
		{
			RETURN_IF_ERROR(document_title.SetConcat(UNI_L("/"), m_htmlified_displayable_base_url));
		}
	}
	else
#endif
	{
		RETURN_IF_ERROR(document_title.Set(m_htmlified_displayable_base_url));
	}


	// Write the document.
#ifdef _LOCALHOST_SUPPORT_
	OpString dirstyle;
	TRAP_AND_RETURN(rc, g_pcfiles->GetFileURLL(PrefsCollectionFiles::StyleDirFile, &dirstyle));
	RETURN_IF_ERROR(OpenDocument(document_title.CStr(), dirstyle.CStr()));
#else
	RETURN_IF_ERROR(OpenDocument(document_title.CStr(), NULL));
#endif

	m_url.WriteDocumentDataUniSprintf(UNI_L(" <base href=\"%s%s\">\n"), m_htmlified_url, dirend_char);

	RETURN_IF_ERROR(OpenBody(Str::S_FOLDER_LISTING_TEXT));

	RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("<h2>")));

	// Provide links to each parent directory in the hierarchy.
	size_t len_htmlified = uni_strlen(m_htmlified_url);
	size_t len_displayable = uni_strlen(m_htmlified_displayable_base_url);
	size_t idx_htmlified = 0, idx_displayable = 0;
	uni_char *protocolsuffix = NULL;
	if (NULL != (protocolsuffix = uni_strstr(m_htmlified_url, UNI_L("://"))))
	{
		uni_char *thirdslash = uni_strchr(protocolsuffix + 3, '/');
		if (thirdslash)
		{
			idx_htmlified = thirdslash - m_htmlified_url + 1;
			if(!is_local_file)
			{
				m_url.WriteDocumentDataUniSprintf(UNI_L("<a href=\"%.*s\">%.*s</a>"), idx_htmlified, m_htmlified_url, idx_htmlified, m_htmlified_url);
			}
		}
		else
		{
			idx_htmlified = static_cast<size_t>(-1);
		}
	}
	else
	{
		idx_htmlified = static_cast<size_t>(-1);
	}
	if (NULL != (protocolsuffix = uni_strstr(m_htmlified_displayable_base_url, UNI_L("://"))))
	{
		uni_char *thirdslash = uni_strchr(protocolsuffix + 3, '/');
		if (thirdslash)
		{
			idx_displayable = thirdslash - m_htmlified_displayable_base_url + 1;
		}
	}

	if (static_cast<size_t>(-1) == idx_htmlified)
	{
		m_url.WriteDocumentDataUniSprintf(UNI_L("%s%s</h2>\n\n"),
										  m_htmlified_url, displayable_dirend_char);
	}
	else
	{
#ifndef SYS_CAP_FILESYSTEM_HAS_DRIVES
		if (is_local_file)
		{
			// Add the initial slash manually, as it does not have a
			// left-hand-side component.
			m_url.WriteDocumentDataUniSprintf(UNI_L("<a href=\"%s\">/</a>"), localhost_prefix);
		}
#endif
		while (idx_htmlified < len_htmlified && idx_displayable < len_displayable)
		{
			uni_char *nextslash_htmlified = uni_strchr(m_htmlified_url + idx_htmlified, '/');
			if (!nextslash_htmlified)
			{
				nextslash_htmlified = m_htmlified_url + len_htmlified;
			}
			uni_char *nextslash_displayable =
				uni_strchr(m_htmlified_displayable_base_url + idx_displayable, pathsepchar);
			if (!nextslash_displayable)
			{
				nextslash_displayable = m_htmlified_displayable_base_url + len_displayable;
			}
			int temp_idx_htmlified = nextslash_htmlified - m_htmlified_url;
			int temp_idx_displayable = nextslash_displayable - m_htmlified_displayable_base_url;

			m_url.WriteDocumentDataUniSprintf(UNI_L("<a href=\"%.*s/\">%.*s</a>/"),
											 temp_idx_htmlified, m_htmlified_url,
											 temp_idx_displayable - idx_displayable, &m_htmlified_displayable_base_url[idx_displayable]);

			idx_htmlified = temp_idx_htmlified + 1;
			idx_displayable = temp_idx_displayable + 1;
		}
		m_url.WriteDocumentData(URL::KNormal, UNI_L("</h2>\n\n"));
	}

	// Clean up.
	delete[] m_temp_base; m_temp_base = NULL;
	delete[] m_htmlified_url; m_htmlified_url = NULL;
	delete[] m_displayable_base_url; m_displayable_base_url = NULL;
	delete[] m_htmlified_displayable_base_url; m_htmlified_displayable_base_url = NULL;

	return OpStatus::OK;
}
Esempio n. 2
0
OP_STATUS OperaPlugins::GenerateData()
{
#ifdef _LOCALHOST_SUPPORT_
	RETURN_IF_ERROR(OpenDocument(Str::SI_PLUGIN_LIST_TEXT, PrefsCollectionFiles::StylePluginsFile));
#else
	RETURN_IF_ERROR(OpenDocument(Str::SI_PLUGIN_LIST_TEXT));
#endif
	OpString disabled_plugin_string;
	RETURN_IF_ERROR(g_languageManager->GetString(Str::SI_IDSTR_PLUGIN_DISABLED, disabled_plugin_string));

	BOOL global_state = g_pcdisplay->GetIntegerPref(PrefsCollectionDisplay::PluginsEnabled) != 0;
	OpAutoVector<OpString> plugin_path_list;
	OpVector<PluginViewer> filtered_viewer_list;

	// Get strings
	OpString enable, disable, details, description, refresh, global_enable;
	RETURN_IF_ERROR(JSSafeLocaleString(&enable, Str::S_LITERAL_ENABLE));
	RETURN_IF_ERROR(JSSafeLocaleString(&disable, Str::S_LITERAL_DISABLE));
	RETURN_IF_ERROR(g_languageManager->GetString(Str::S_PLUGIN_LIST_DETAILS, details));
	RETURN_IF_ERROR(g_languageManager->GetString(Str::S_PLUGIN_LIST_PLUGIN_DESC, description));
	RETURN_IF_ERROR(g_languageManager->GetString(Str::S_PLUGIN_REFRESH, refresh));
	RETURN_IF_ERROR(g_languageManager->GetString(Str::DI_IDM_PLUGINS_TOGGLE, global_enable));
#ifdef ABOUT_PLUGINS_SHOW_ARCHITECTURE
	OpString arch_label, arch_native, arch_non_native;
	RETURN_IF_ERROR(g_languageManager->GetString(Str::S_PLUGIN_LIST_ARCHITECTURE, arch_label));
	RETURN_IF_ERROR(g_languageManager->GetString(Str::S_PLUGIN_LIST_ARCHITECTURE_NATIVE, arch_native));
	RETURN_IF_ERROR(g_languageManager->GetString(Str::S_PLUGIN_LIST_ARCHITECTURE_NON_NATIVE, arch_non_native));
#endif // ABOUT_PLUGINS_SHOW_ARCHITECTURE

	OpString js_code;
	PluginViewers *plugin_viewer_list = g_plugin_viewers;	// Cache global
	const bool detecting = plugin_viewer_list->IsDetecting();
	// TODO CORE-40424: should either consolidate non-NS4P_COMPONENT_PLUGINS and
	// NS4P_COMPONENT_PLUGINS code so that are handled similarly or make a clear
	// separation between them using ifdefery. See http://critic-dev.oslo.osa/showcomment?chain=64850.
	if (detecting)
	{
		RETURN_IF_ERROR(js_code.Set(" <script type=\"text/javascript\">\n"
		                            "   window.onload = function()\n"
		                            "   {\n"
		                            "     setTimeout(\"window.location.reload()\", 3000);\n"
		                            "   };\n"
		                            " </script>\n"));
	}
	else
	{
		// Force sync detection if async did not finish already. Only relevant
		// for the non-NS4P_COMPONENT_PLUGINS code which never handles the
		// if-clause above.
		// TODO CORE-40424: This can be handled in a same way as the "new" code
		// given proper implementation of IsDetecting().
		plugin_viewer_list->MakeSurePluginsAreDetected();

		UINT numplugins = plugin_viewer_list->GetPluginViewerCount();

		RETURN_IF_ERROR(js_code.Set(" <script type=\"text/javascript\">\n  var plugin_list = ["));

		// First loop over plug-ins to create filtered list and javascript array for use on page
		for (UINT i = 0; i < numplugins; ++ i)
		{
			// Get the numbered plug-in
			PluginViewer *candidate_viewer = plugin_viewer_list->GetPluginViewer(i);
			const uni_char *plugin_path = candidate_viewer ? candidate_viewer->GetPath() : NULL;
			if (!plugin_path)
				continue;

			// Check for duplicate registrations
			BOOL is_duplicate = FALSE;
			UINT pathlistlen = plugin_path_list.GetCount();
			if (pathlistlen)
			{
				for (UINT j = 0; !is_duplicate && j < pathlistlen; ++j)
				{
					is_duplicate = !plugin_path_list.Get(j)->Compare(plugin_path);
				}
			}
			if (is_duplicate)
				continue;

			RETURN_IF_ERROR(filtered_viewer_list.Add(candidate_viewer));
			OpString escaped_path;
			RETURN_IF_ERROR(escaped_path.Set(candidate_viewer->GetPath()));
			RETURN_IF_ERROR(escaped_path.ReplaceAll(UNI_L("\\"), UNI_L("\\\\")));
			RETURN_IF_ERROR(escaped_path.ReplaceAll(UNI_L("'"), UNI_L("\\'")));
			RETURN_IF_ERROR(js_code.AppendFormat(UNI_L("\n  {enabled:%i, path:'%s'},"),
			                candidate_viewer->IsEnabled(),
			                escaped_path.CStr()));

			// Remember this entry
			OpString *s = OP_NEW(OpString, ());
			RETURN_OOM_IF_NULL(s);
			OP_STATUS st = s->Set(plugin_path);
			if (OpStatus::IsError(st))
			{
				OP_DELETE(s);
				return st;
			}
			plugin_path_list.Add(s);
		}

		RETURN_IF_ERROR(js_code.Append(
			"  ];\n\n"
			"  function togglePlugin(id, link)\n"
			"  {\n"
			"   var plugin = plugin_list[id], ret;\n"
			"   if (plugin && (ret = opera.togglePlugin(plugin.path, !plugin.enabled)) != -1)\n"
			"   {\n"
			"    plugin.enabled = ret;\n"
			"    document.getElementById('plug_'+id).className = ret ? '' : 'disabled';\n"));
		RETURN_IF_ERROR(js_code.AppendFormat(
			UNI_L("    link.textContent = ret ? \"%s\" : \"%s\";\n"), disable.CStr(), enable.CStr()));
		RETURN_IF_ERROR(js_code.Append(
			"   }\n"
			"   return false;\n"
			"  }\n\n"
			"  function toggleGlobal(enabled)\n"
			"  {\n"
			"   opera.setPreference('Extensions', 'Plugins', enabled ? '1' : '0');\n"
			"   document.body.id = enabled ? 'plugins-enabled' : 'plugins-disabled';\n"
			"  }\n\n"
			"  function toggleAllDetails(expand)\n"
			"  {\n"
			"   var names = document.getElementsByTagName('legend');\n"
			"   for (var i=0; i<names.length; i++)\n"
			"   {\n"
			"    toggleDetails(names[i], expand);\n"
			"   }\n"
			"  }\n\n"
			"  function toggleDetails(name, expand)\n"
			"  {\n"
			"   name.className = name.expanded=expand ? 'expanded' : '';\n"
			"   name.mime.style.height = name.mime.scrollHeight+'px';\n"
			"   name.mime.offsetHeight;\n"
			"   if (!expand)\n"
			"    name.mime.style.height = '0';\n"
			"  }\n\n"
			"  window.addEventListener('load', function()\n"
			"  {\n"
			"   // it's guaranteed to have same number of these elements\n"
			"   var names = document.getElementsByTagName('legend');\n"
			"   var mimes = document.getElementsByClassName('mime');\n\n"
			"   for (var i=0; i<names.length; i++)\n"
			"   {\n"
			"    /* after expanding, set height to auto so that\n"
			"       layout is kept fluid on resizing */\n"
			"    mimes[i].addEventListener('transitionEnd', function(e)\n"
			"    {\n"
			"     if (e.propertyName != 'height') return;\n"
			"     if (parseInt(this.style.height) != '0')\n"
			"      this.style.height = 'auto';\n"
			"    }, false);\n\n"
			"    // save reference to mime block in clicked element\n"
			"    names[i].mime = mimes[i];\n"
			"    names[i].addEventListener('click', function()\n"
			"    {\n"
			"     toggleDetails(this, this.expanded=!this.expanded);\n"
			"    }, false);\n\n"
			"    names[i].firstChild.plugin_id = i;\n"
			"    names[i].firstChild.addEventListener('click', function(e)\n"
			"    {\n"
			"     togglePlugin(this.plugin_id, this);\n"
			"     e.preventDefault();\n"
			"     e.cancelBubble = true;\n"
			"    }, false);\n"
			"   }\n"
			"  }, false);\n"
			" </script>\n"));
	}

	RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, js_code.CStr()));
	RETURN_IF_ERROR(OpenBody(Str::SI_PLUGIN_LIST_TEXT, global_state ? UNI_L("plugins-enabled") : UNI_L("plugins-disabled")));

	UINT32 filtered_count = filtered_viewer_list.GetCount();

	// Link for enabling/disabling the plugins globally
	RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal,
		UNI_L("<label><input type=\"checkbox\" onchange=\"toggleGlobal(this.checked)\"")));
	if (detecting)
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L(" disabled=\"disabled\"")));
	RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal,
		global_state ? UNI_L(" checked=\"checked\">") : UNI_L(">")));
	RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, global_enable.CStr()));
	RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</label>\n")));

	RETURN_IF_ERROR(m_url.WriteDocumentDataUniSprintf(UNI_L("<p id=\"details\">")));

	// Link for toggling mime type details (details are initially hidden)
	if (filtered_count)
	{
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal,
			UNI_L("<label><input type=\"checkbox\" onchange=\"toggleAllDetails(this.checked)\">")));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, details.CStr()));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</label>\n")));
	}

	// Link for refreshing plugins directory to see if plugins were added/removed
	if (!detecting)
	{
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal,
			UNI_L("<a href=\"#\" onclick=\"navigator.plugins.refresh(true);return false;\">")));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, refresh.CStr()));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</a>")));
	}
	RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</p>\n")));

	// Output filtered plug-ins on page
	for (UINT i = 0; i < filtered_count; ++ i)
	{
		PluginViewer *candidate_viewer = filtered_viewer_list.Get(i);

		// Get name of plug-in and write it as header
		const uni_char *plugin_path = candidate_viewer->GetPath();
		const uni_char *plugin_name = candidate_viewer->GetProductName();
		const uni_char *plugin_description = candidate_viewer->GetDescription();
		const uni_char *plugin_version = candidate_viewer->GetVersion();
		BOOL disabled = !candidate_viewer->IsEnabled();

		// Start plug-in block
		RETURN_IF_ERROR(m_url.WriteDocumentDataUniSprintf(UNI_L("<fieldset id=\"plug_%i\"%s>\n<legend>"),
			i,
			disabled ? UNI_L(" class=\"disabled\"") : UNI_L("")));

		// Link for disabling/enabling plug-in
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("<a href=\"#\">")));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, disabled ? enable.CStr() : disable.CStr()));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</a>\n")));

		// Name
		if (plugin_name)
			RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, plugin_name));

		uni_char *tmp;

		// Version - shown if non-empty
		if (plugin_version && *plugin_version)
		{
			RETURN_OOM_IF_NULL(tmp = HTMLify_string(plugin_version));
			ANCHOR_ARRAY(uni_char, tmp);
			RETURN_IF_ERROR(m_url.WriteDocumentDataUniSprintf(UNI_L("<span> - %s</span>"), tmp));
			ANCHOR_ARRAY_DELETE(tmp);
		}
		else
		{
			plugin_version = UNI_L("");
		}

		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</legend>\n<div>\n")));

		/* Description - shown if non-empty and different from name and version.
		   It's not htmlified because it contains links. Instead function for
		   stripping html tags is used that leaves A tags only. */
		if (plugin_description
			&& uni_strlen(plugin_description)
			&& !uni_stri_eq(plugin_name, plugin_description)
			&& !uni_stri_eq(plugin_description, plugin_version))
		{
			OpString desc;
			RETURN_IF_ERROR(desc.Set(plugin_description));
			StripHTMLTags(desc.CStr(), desc.Length());
			RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("<div>")));
			RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, description.CStr()));
			RETURN_IF_ERROR(m_url.WriteDocumentDataUniSprintf(UNI_L(": %s</div>\n"), desc.CStr()));
		}

#ifdef ABOUT_PLUGINS_SHOW_ARCHITECTURE
		// Plugin architecture. Different from COMPONENT_PLUGIN means non-native.
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("<div>")));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, arch_label.CStr()));
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L(": ")));

		if (candidate_viewer->GetComponentType() == COMPONENT_PLUGIN)
			RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, arch_native.CStr()));
		else
			RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, arch_non_native.CStr()));

		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</div>\n")));
#endif // ABOUT_PLUGINS_SHOW_ARCHITECTURE

		// Path to the plug-in
		RETURN_OOM_IF_NULL(tmp = HTMLify_string(plugin_path));
		ANCHOR_ARRAY(uni_char, tmp);
		RETURN_IF_ERROR(m_url.WriteDocumentDataUniSprintf(UNI_L("<address>%s</address>\n"), tmp));
		ANCHOR_ARRAY_DELETE(tmp);

		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("<div class=\"mime\"><table>\n")));

		// Find MIME types associated with this plug-in
		Viewer* viewer;
		ChainedHashIterator* viewer_iter;
		g_viewers->CreateIterator(viewer_iter);
		if (viewer_iter != NULL)
		{
			OpAutoPtr<OpHashIterator> viewer_iter_ap(viewer_iter);
			while (viewer_iter && (viewer=g_viewers->GetNextViewer(viewer_iter)) != NULL)
			{
				// Iterate over all plug-ins associated with this MIME type
				unsigned int numpluginviewers = viewer->GetPluginViewerCount();
				for (unsigned int k = 0; k < numpluginviewers; ++ k)
				{
					const PluginViewer *p = viewer->GetPluginViewer(k);
					if (p && p->GetPath() && uni_strcmp(p->GetPath(), plugin_path) == 0)
					{
						// This is us.

						// MIME type
						const uni_char *mime_type = viewer->GetContentTypeString();
						if (mime_type)
						{
							int mimestart = 0;

							RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L(" <tr>\n  <td>")));

							// Split string at "|"s
							for(int i = mimestart = 0; mime_type[i]; ++ i)
							{
								if (mime_type[i] == '|')
								{
									RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, mime_type + mimestart, i - mimestart));
									RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("<br>\n  ")));

									mimestart = i + 1;
								}
							}

							// Print the remainder of the string
							RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, &mime_type[mimestart]));
							RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</td>\n")));
						}

						// Description
						OpString description;
						RETURN_IF_ERROR(p->GetTypeDescription(mime_type, description));
						RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("  <td>")));
						RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, description));
						RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</td>\n")));

						// Extensions
						RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("  <td>")));

						const uni_char *extensions = viewer->GetExtensions();
						if (extensions)
						{
							int extstart = 0;

							// Split string at "|"s
							for (int i = 0; extensions[i]; ++ i)
							{
								if(extensions[i] == '|')
								{
									RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, extensions + extstart, extstart - i));
									RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("<br>\n  ")));

									extstart = i + 1;
								}
							}

							// Print the remainder of the string
							RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KHTMLify, &extensions[extstart]));
						}
						RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</td>\n </tr>\n")));
					}
				}
			}
		}

		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</table></div>\n")));

		// Finish plug-in block
		RETURN_IF_ERROR(m_url.WriteDocumentData(URL::KNormal, UNI_L("</div>\n</fieldset>\n")));
	}

	if (detecting)
	{
		OpString detecting_str;
		RETURN_IF_ERROR(g_languageManager->GetString(Str::S_PLUGIN_DETECTING, detecting_str));
		RETURN_IF_ERROR(m_url.WriteDocumentDataUniSprintf(UNI_L("<p>%s</p>\n"), detecting_str.CStr()));
	}
	else if (!filtered_viewer_list.GetCount())
	{
		OpString none_found;
		RETURN_IF_ERROR(g_languageManager->GetString(Str::SI_IDSTR_NONE_FOUND, none_found));
		RETURN_IF_ERROR(m_url.WriteDocumentDataUniSprintf(UNI_L("<p>%s</p>\n"), none_found.CStr()));
	}

	// Finish off
	return CloseDocument();
}
/*!
  Add program information into database
  \param[in]
  */
static BOOL edit_pg_into_db(scan_pg_info_t *p_pg_info, u16 similar_idx)
{
  //Edit program into database
  event_t evt = {SCAN_EVT_PG_FOUND};
  db_dvbs_ret_t db_ret = DB_DVBS_OK;
  dvbs_prog_node_t *p_pg_node = g_p_scan_priv->pg_list + similar_idx;
  u16  pg_name_uni[DB_DVBS_MAX_NAME_LENGTH+1] = {0};
  
  
  //the below is read only for user
  MT_ASSERT(p_pg_node->s_id == p_pg_info->s_id);

  #ifndef SUPPORT_NIGNORE_PRECODE
  {
  	u8 filter_name[MAX_SVC_NAME_SUPPORTED] = {0};
  	str_uni_filter(filter_name, p_pg_info->name);
  	memset(p_pg_info->name, 0, MAX_SVC_NAME_SUPPORTED);
  	memcpy(p_pg_info->name, filter_name, MAX_SVC_NAME_SUPPORTED);
  }
  #endif
  
  //make a name for no name for some pgs
  if(strlen((char *)p_pg_info->name) == 0)
  {
    u8 p_name[MAX_SVC_NAME_SUPPORTED] = {0};
    u8 name_size = 0;
    if(p_pg_info->video_pid != 0)
    {
      sprintf((char *)p_name,"%s%d","TV CH",p_pg_info->s_id);
    }
    else
    {
      sprintf((char *)p_name,"%s%d","RADIO CH",p_pg_info->s_id);
    }
    name_size = strlen((char *)p_name);
    if(name_size > MAX_SVC_NAME_SUPPORTED)
    {
      name_size = MAX_SVC_NAME_SUPPORTED;
    }
    strncpy((char *)p_pg_info->name,(char *)p_name,name_size);
  }
  
  dvb_to_unicode(p_pg_info->name, MAX_SVC_NAME_SUPPORTED,
    pg_name_uni, DB_DVBS_MAX_NAME_LENGTH+1);
  
  if((p_pg_node->hide_flag == 1)
    ||(p_pg_node->video_pid != p_pg_info->video_pid)
    || (p_pg_node->audio_ch_num != p_pg_info->audio_ch_num)
    || (memcmp(p_pg_node->audio, p_pg_info->audio,
      sizeof(audio_t) * p_pg_info->audio_ch_num)) 
    || (p_pg_node->pcr_pid != p_pg_info->pcr_pid) 
    || (p_pg_node->skp_flag != 0)
    || (p_pg_node->is_scrambled != p_pg_info->is_scrambled) 
    || (uni_strcmp(p_pg_node->name, pg_name_uni) != 0)
//    || (p_pg_node->volume_compensate != p_pg_info->volume_compensate) 
#ifdef LOGIC_NUM_SUPPORT
    || (p_pg_node->logical_num != p_pg_info->logical_num && p_pg_info->logical_num != 0)
#endif
    //|| (p_pg_node->bouquet_id != p_pg_info->bouquet_id)
    )
  {
#ifdef AISET_BOUQUET_SUPPORT
    switch(find_show_flag_by_sid(p_pg_info->s_id))
    {
      case 0x01://the service is always showing on service list
        p_pg_node->hide_flag = 0;
        break;    
      case 0x02://the service is always hiding on service list
        p_pg_node->hide_flag = 1;
        break;    
      case 0x00://if service is not authorized by operator then the service is hided on service list
        p_pg_node->hide_flag = 0;
        p_pg_node->operator_flag = 1;
        break;    
      default:
        break;
    }
#else
    p_pg_node->hide_flag = 0;
#endif
    p_pg_node->pcr_pid = p_pg_info->pcr_pid;
    p_pg_node->video_pid = p_pg_info->video_pid;
    uni_strncpy(p_pg_node->name, pg_name_uni, DB_DVBS_MAX_NAME_LENGTH);
    p_pg_node->tv_flag = (p_pg_node->video_pid != 0) ? 1 : 0;
    p_pg_node->skp_flag = 0;
    p_pg_node->audio_ch_num = p_pg_info->audio_ch_num;
    p_pg_node->is_scrambled = p_pg_info->is_scrambled;
//    p_pg_node->volume_compensate = p_pg_info->volume_compensate;
    p_pg_node->ca_system_id = p_pg_info->ca_system_id;
    p_pg_node->service_type = check_service_type(p_pg_info);
    p_pg_node->video_type = p_pg_info->video_type;
#ifdef LOGIC_NUM_SUPPORT
    //p_pg_node->logical_num = p_pg_info->logical_num;
    p_pg_info->logical_num = find_logic_number_by_sid(p_pg_info->s_id);
    if(p_pg_info->logical_num)
    {
      p_pg_node->logical_num = p_pg_info->logical_num;
    }
    else
    {
      u16 un_india_ts_logic_num = sys_status_get_default_logic_num();
      p_pg_info->logical_num = un_india_ts_logic_num;
      p_pg_node->logical_num = p_pg_info->logical_num;
      un_india_ts_logic_num++;
      sys_status_set_default_logic_num(un_india_ts_logic_num);
    }
#endif
    //p_pg_node->bouquet_id = p_pg_info->bouquet_id;
    memcpy(p_pg_node->audio, p_pg_info->audio,
      sizeof(audio_t)*p_pg_node->audio_ch_num);
    db_ret = db_dvbs_edit_program(p_pg_node);
    MT_ASSERT(db_ret == DB_DVBS_OK);
  }
  
  evt.data1 = (u32)p_pg_node;
  ap_frm_send_evt_to_ui(APP_SCAN, &evt);
 
  return TRUE;
}