View Issue Details

IDProjectCategoryView StatusLast Update
0002931Composrgalleriespublic2020-06-25 01:19
ReporterChris GrahamAssigned To 
SeverityFeature-request 
Status non-assignedResolutionopen 
Product Version 
Fixed in Version 
Summary0002931: PDF slideshow display
DescriptionDisplay of PDFs via either slideshare, or an integrated flipbook reader.
Additional InformationSome old code from a client is attached, it is nowhere compatible with modern Composr but would serve to help reconstruct this.
TagsNo tags attached.
Time estimation (hours)10
Sponsorship open

Activities

Chris Graham

2016-11-21 14:35

administrator  

slideshare.diff (39,666 bytes)
--- themes/default/templates/GALLERY_VIDEO_PRESENTATION.tpl	(revision 0)
+++ themes/default/templates/GALLERY_VIDEO_PRESENTATION.tpl	(revision 0)
@@ -0,0 +1,19 @@
+{$SET,DOC_ID,{$SLIDESHARE_DOC_ID,{DOC_ID_URL},{DOC_ID_TITLE},{DOC_ID_ORIG_FILENAME}}}
+
+{+START,IF_EMPTY,{$GET,DOC_ID}}
+	{+START,BOX,,,med}
+		{!SLIDESHOW_STILL_UPLOADING}
+	{+END}
+{+END}
+
+{+START,IF_NON_EMPTY,{$GET,DOC_ID}}
+	<div style="width:425px">
+		<object width="425" height="355">
+			<param name="movie" value="http://static.slidesharecdn.com/swf/{$GET*,DOC_ID}" />
+			<param name="allowFullScreen" value="true"/>
+			<param name="allowScriptAccess" value="always"/>
+
+			<embed src="http://static.slidesharecdn.com/swf/{$GET*,DOC_ID}" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed>
+		</object>
+	</div>
+{+END}
--- themes/default/templates/GALLERY_VIDEO_TAR.tpl	(revision 0)
+++ themes/default/templates/GALLERY_VIDEO_TAR.tpl	(revision 0)
@@ -0,0 +1,46 @@
+<div class="p1-scroll"{$, style="width: {WIDTH*}px; height: {HEIGHT*}px;"}>
+	{$SET,pg_it,1}
+	{+START,LOOP,CONTENT}
+		<div style="display: none;" id="fp_page_{$GET*,pg_it}">
+			<div class="container" style="background:url({$THUMBNAIL*,{IMG_URL},602x430{$,{WIDTH}x{HEIGHT}},galleries_thumbs,,,pad,start_if_vertical,#ED1C23}) no-repeat 0 0;">
+			</div>
+		</div>
+		{$INC,pg_it}
+	{+END}
+	<div class="nav-pages">
+		<ul class="pages1">
+			<li>
+				<a onclick="return fp_animation_func(-1);" href="#"><img alt="{!PREVIOUS}" src="{$IMG*,tgvh/reply-prev}"/></a>
+			</li>
+			<li>
+				<a onclick="return toggle_fp_animation();" href="#"><img alt="{!PAUSE}" src="{$IMG*,tgvh/reply-pause}"/></a>
+			</li>
+			<li>
+				<a onclick="return fp_animation_func(1);" href="#"><img alt="{!NEXT}" src="{$IMG*,tgvh/reply-next}"/></a>
+			</li>
+		</ul>
+		<ul class="pages">
+			{$SET,pg_it,1}
+			{+START,LOOP,CONTENT}
+				<li id="fp_page_link_{$GET*,pg_it}">
+					<a onclick="clear_fp_animation(); return fp_goto_func({$GET*,pg_it},{CONTENT});" href="#">{$GET*,pg_it}</a>
+				</li>
+				{$INC,pg_it}
+			{+END}
+		</ul>
+	</div>
+
+	<script type="text/javascript">// <![CDATA[
+		window.fp_counter={CONTENT}; // Set to last one, so cycles onto first when we load
+
+		function fp_animation_func(dir)
+		{
+			return fp_goto_func(window.fp_counter+dir,{CONTENT});
+		}
+
+		addEventListenerAbstract(window,'load',function () {
+			create_fp_animation();
+			fp_animation_func(1);
+		} );
+	//]]></script>
+</div>
--- themes/default/templates/ATTACHMENT_PRESENTATION.tpl	(revision 0)
+++ themes/default/templates/ATTACHMENT_PRESENTATION.tpl	(revision 0)
@@ -0,0 +1,19 @@
+{$SET,DOC_ID,{$SLIDESHARE_DOC_ID,{DOC_ID_URL},{DOC_ID_TITLE},{DOC_ID_ORIG_FILENAME}}}
+
+{+START,IF_EMPTY,{$GET,DOC_ID}}
+	{+START,BOX,,,med}
+		{!SLIDESHOW_STILL_UPLOADING}
+	{+END}
+{+END}
+
+{+START,IF_NON_EMPTY,{$GET,DOC_ID}}
+	<div style="width:425px">
+		<object width="425" height="355">
+			<param name="movie" value="http://static.slidesharecdn.com/swf/{$GET*,DOC_ID}" />
+			<param name="allowFullScreen" value="true"/>
+			<param name="allowScriptAccess" value="always"/>
+		
+			<embed src="http://static.slidesharecdn.com/swf/{$GET*,DOC_ID}" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed>
+		</object>
+	</div>
+{+END}
--- adminzone/pages/modules/admin_config.php	2011-03-13 13:30:11.823629700 +0000
+++ adminzone/pages/modules/admin_config.php	2010-12-01 10:48:01.813384400 +0000
@@ -65,12 +65,14 @@
 										'enable_keyword_density_check','enable_spell_check','enable_markup_validation','enable_image_fading','users_online_time','auto_submit_sitemap',
 										'user_postsize_errors','automatic_meta_extraction','is_on_emoticon_choosers','no_stats_when_closed',
 										'deeper_admin_breadcrumbs','has_low_memory_limit','is_on_comcode_page_children','global_donext_icons','no_bot_stats',
-										'java_upload','java_ftp_host','java_username','java_password','java_ftp_path','filesystem_caching',
+										'java_upload','java_ftp_host','java_username','java_password','java_ftp_path','filesystem_caching','allow_slideshare','slideshare_api_key',
										'check_broken_urls','advanced_admin_cache','collapse_user_zones','google_analytics','fixed_width','show_screen_actions','show_content_tagging','show_content_tagging_inline',
 										);
 
 		foreach ($config_options as $option)
 			delete_config_option($option);
+
+		$GLOBALS['SITE_DB']->drop_if_exists('slideshare_mapping');
 	}
 
 	/**
@@ -218,6 +220,21 @@
 			add_config_option('JAVA_FTP_PASSWORD','java_password','line','return \'someone@example.com\';','SITE','JAVA_UPLOAD');
 			add_config_option('JAVA_FTP_PATH','java_ftp_path','line','return \'/public_html/uploads/incoming/\';','SITE','JAVA_UPLOAD');
 		}
+		if ((is_null($upgrade_from)) || ($upgrade_from<11))
+		{
+			add_config_option('ALLOW_SLIDESHARE','allow_slideshare','tick','return function_exists(\'sha1\')?\'1\':NULL;','FEATURE','SLIDESHARE_INTEGRATION');
+			add_config_option('SLIDESHARE_API_KEY','slideshare_api_key','line','return function_exists(\'sha1\')?\'\':NULL;','FEATURE','SLIDESHARE_INTEGRATION');
+			add_config_option('SLIDESHARE_USERNAME','slideshare_username','line','return function_exists(\'sha1\')?\'\':NULL;','FEATURE','SLIDESHARE_INTEGRATION');
+			add_config_option('SLIDESHARE_PASSWORD','slideshare_password','line','return function_exists(\'sha1\')?\'\':NULL;','FEATURE','SLIDESHARE_INTEGRATION');
+			add_config_option('SLIDESHARE_SECRET','slideshare_secret','line','return function_exists(\'sha1\')?\'\':NULL;','FEATURE','SLIDESHARE_INTEGRATION');
+
+			$GLOBALS['SITE_DB']->create_table('slideshare_mapping',array(
+				'id'=>'*AUTO',
+				's_slideshare_id'=>'ID_TEXT',
+				's_local_file'=>'URLPATH',
+				's_embed_key'=>'SHORT_TEXT',
+			));
+		}
 
 		if ((!is_null($upgrade_from)) && ($upgrade_from<8))
 		{
--- sources/hooks/systems/addon_registry/core_rich_media.php	2011-03-13 13:31:31.138985900 +0000
+++ sources/hooks/systems/addon_registry/core_rich_media.php	2010-09-30 02:12:10.727582600 +0100
@@ -84,6 +84,7 @@
 			'ATTACHMENTS_BROWSER.tpl',
 			'ATTACHMENTS_BROWSER_ATTACHMENT.tpl',
 			'ATTACHMENT_FLV.tpl',
+			'ATTACHMENT_PRESENTATION.tpl',
 			'ATTACHMENT_DOWNLOAD.tpl',
 			'ATTACHMENT_DOWNLOAD_REMOTE.tpl',
 			'ATTACHMENT_IMG.tpl',

--- sources/hooks/systems/addon_registry/galleries.php	2011-03-13 13:31:31.850026600 +0000
+++ sources/hooks/systems/addon_registry/galleries.php	2010-09-30 02:12:10.757582600 +0100
@@ -111,6 +111,7 @@
 			'GALLERY_VIDEO_GENERAL.tpl',
 			'GALLERY_VIDEO_QT.tpl',
 			'GALLERY_VIDEO_RM.tpl',
+			'GALLERY_VIDEO_PRESENTATION.tpl',
 			'GALLERY_ENTRY_SCREEN.tpl',
 			'GALLERY_FLOW_ENTRY.tpl',
 			'GALLERY_FLOW_MODE_SCREEN.tpl',

--- lang/EN/config.ini	2011-03-13 13:30:39.672302300 +0000
+++ lang/EN/config.ini	2010-12-01 10:47:59.493251700 +0000
@@ -316,3 +316,14 @@
 FORUM_CURRENTLY_UNSET=You currently have no valid selection for the '{1}' option. When you save this form, the Home forum will be used unless you set something different.
 FILE_SYSTEM_CACHING=File-system caching
 CONFIG_OPTION_filesystem_caching=Use file-system cacheing for the block cache (amongst others), instead of the database. This is only recommended for servers where the database has a limited capacity or where database load is a problem.
+CONFIG_OPTION_allow_slideshare=Allow presentation (PDF, PPT, etc) uploads to be automatically uploaded to slide-share and embedded using this.
+ALLOW_SLIDESHARE=Allow slideshare integration
+SLIDESHARE_API_KEY=Slideshare <acronym title="Application Programming Interface">API</acronym> key
+CONFIG_OPTION_slideshare_api_key=This is your <acronym title="Application Programming Interface">API</acronym> key for automatic upload of presentation to Slideshare. You will need this for presentation upload support to work. <a href="http://www.slideshare.net/developers/applyforapi">Apply for an <acronym title="Application Programming Interface">API</acronym> key</a>.
+SLIDESHARE_INTEGRATION=Slideshare integration
+SLIDESHARE_USERNAME=Slideshare username
+CONFIG_OPTION_slideshare_username=Your slideshare account's username.
+SLIDESHARE_PASSWORD=Slideshare password
+CONFIG_OPTION_slideshare_password=Your slideshare account's password.
+SLIDESHARE_SECRET=Slideshare secret
+CONFIG_OPTION_slideshare_secret=The slideshare secret that was sent to you when your <acronym title="Application Programming Interface">API</acronym> key was validated.

--- lang/EN/critical_error.ini	2011-03-13 13:30:39.732304000 +0000
+++ lang/EN/critical_error.ini	2010-12-01 10:47:59.471250400 +0000
@@ -216,3 +216,5 @@
 HTACCESS_SEO_PROBLEM=It looks like you have enabled &ldquo;New Style Short URLs&rdquo; and added a custom zone, but may not have edited your <kbd>.htaccess</kbd> file to refer to the new zone by extending the default rewrite-rules.
 NO_INTEGERS_TEMPLATE=Programming error: Integers and/or floats should not be passed into templates (<var>{1}</var>): convert them to strings.
 NO_HIPHOP=This feature does not work on alternative PHP implementations.
+SLIDESHOW_API_ERROR=We got an error when trying to upload the error to slideshow. Please try again, or if it continues to fail, please contact us.<br /><br />{1}
+SLIDESHOW_STILL_UPLOADING=This presentation is still being processed. It should be available very soon.

--- sources/images.php	2011-03-13 13:30:58.227349700 +0000
+++ sources/images.php	2011-01-03 23:07:52.993767200 +0000
@@ -19,6 +19,15 @@
  */
 
 /**
+ * Standard code module initialisation function.
+ */
+function init__images()
+{
+	global $SLIDESHARE_DOC_IDS;
+	$SLIDESHARE_DOC_IDS=array();
+}
+
+/**
  * Get the maximum allowed image size, as set in the configuration.
  *
  * @return integer		The maximum image size
@@ -419,7 +606,179 @@
 
 	require_code('mime_types');
 	$mime_type=get_mime_type($ext);
-	return ((substr($mime_type,0,6)=='video/') || ((get_option('allow_audio_videos')=='1') && (substr($mime_type,0,6)=='audio/')));
+	if (substr($mime_type,0,6)=='video/') return true;
+	if ((get_option('allow_audio_videos')=='1') && (substr($mime_type,0,6)=='audio/')) return true;
+	if ((get_option('allow_slideshare')=='1') && (is_presentation($name))) return true;
+	if (is_archive($name)) return true;
+	if (is_image($name)) return true;
+	return false;
+}
+
+/**
+ * Find whether the video specified is actually an video, based on file extension
+ *
+ * @param  string			A URL or file path to the video
+ * @return boolean		Whether the string pointed to a file appeared to be a video
+ */
+function is_archive($name)
+{
+	require_code('mime_types');
+	$ext=get_file_extension($name);
+	$mime_type=get_mime_type($ext);
+	if ($mime_type=='application/x-tar') return true;
+	if ($mime_type=='application/zip') return true;
+	return false;
+}
+
+/**
+ * Find whether the uploaded file is a slideshare presentation
+ *
+ * @param  string			A URL or file path to the presentation
+ * @return boolean		Whether the string pointed to a file appeared to be a presentation
+ */
+function is_presentation($name)
+{
+	if (get_option('slideshare_api_key')=='') return false;
+	
+	$ext=get_file_extension($name);
+	return (in_array($ext,array('pdf','ppt','pps','pptx','ppsx','pot','potx','odp')));
+}
+
+/**
+ * Make sure a slide has been uploaded to slideshare
+ *
+ * @param  URLPATH		The URL we have locally
+ * @param  SHORT_TEXT	The title
+ * @param  ID_TEXT		The filename
+ * @return ID_TEXT		The slideshare ID
+ */
+function slideshare_doc_id($url,$title,$orig_filename)
+{
+	global $SLIDESHARE_DOC_IDS;
+	if (array_key_exists($url,$SLIDESHARE_DOC_IDS)) return $SLIDESHARE_DOC_IDS[$url];
+
+	require_code('files');
+
+	if ($title=='') $title=do_lang('PRESENTATION');
+
+	$given_url=$url;
+	if (url_is_local($given_url)) $url=get_custom_base_url().'/'.$url;
+
+	$test=$GLOBALS['SITE_DB']->query_select('slideshare_mapping',array('s_embed_key','s_slideshare_id'),array('s_local_file'=>$url),'',1);
+	if (array_key_exists(0,$test))
+	{
+		$slideshare_id=$test[0]['s_slideshare_id'];
+		if ($test[0]['s_embed_key']!='')
+		{
+			$SLIDESHARE_DOC_IDS[$url]=$test[0]['s_embed_key'];
+			return $test[0]['s_embed_key'];
+		}
+	} else
+	{
+		$slideshare_id=NULL;
+	}
+
+	if (is_null($slideshare_id)) // We need to upload
+	{
+		if (url_is_local($given_url))
+		{
+			$tmp_file=get_custom_file_base().'/'.rawurldecode($given_url);
+		} else
+		{
+			$tmp_file=ocp_tempnam('slideshare');
+			$tmp_file_2=$tmp_file.'.'.get_file_extension($orig_filename);
+			rename($tmp_file,$tmp_file_2);
+			$tmp_file=$tmp_file_2;
+			$tmp_file_handle=fopen($tmp_file,'wb');
+			http_download_file($url,NULL,true,false,'ocPortal',NULL,NULL,NULL,NULL,NULL,$tmp_file_handle);
+			fclose($tmp_file_handle);
+		}
+
+		$post=array(
+			'username'=>get_option('slideshare_username'),
+			'password'=>get_option('slideshare_password'),
+			'slideshow_title'=>$title,
+			//'upload_url'=>$url.((strpos($url,'?')!==false)?'&':'?').'filename='.urlencode($orig_filename),
+		);
+
+		$time=time();
+
+		$hash=sha1(get_option('slideshare_secret').strval($time));
+
+		$files=array('slideshow_srcfile'=>$tmp_file);
+
+		$api_base='http://www.slideshare.net/api/2/upload_slideshow';
+
+		$call=$api_base.'?api_key='.urlencode(get_option('slideshare_api_key')).'&ts='.urlencode(strval($time)).'&hash='.urlencode($hash);
+		$response=http_download_file($call,NULL,true,false,'ocPortal',$post,NULL,NULL,NULL,NULL,NULL,NULL,NULL,6.0,false,$files);
+		if ((file_exists(get_file_base().'/data_custom/slideshare.log')) && (is_writeable(get_file_base().'/data_custom/slideshare.log')))
+		{
+			$log_file=fopen(get_file_base().'/data_custom/slideshare.log','at');
+			fwrite($log_file,date('Y-m-d H:i:s').': '.$call."\n");
+			fwrite($log_file,date('Y-m-d H:i:s').': '.$response."\n\n");
+		}
+
+		if (!url_is_local($given_url))
+			unlink($tmp_file);
+
+		$matches=array();
+		if (preg_match('#<SlideShowUploaded>[\s\n]*<SlideShowID>(.*)</SlideShowID>[\s\n]*</SlideShowUploaded>#',$response,$matches)!=0)
+		{
+			$slideshare_id=$matches[1];
+		} else
+		{
+			warn_exit(do_lang_tempcode('SLIDESHOW_API_ERROR',escape_html($response)));
+		}
+	}
+
+	// Now find embed ID
+
+	$post=array(
+		'username'=>get_option('slideshare_username'),
+		'password'=>get_option('slideshare_password'),
+		'slideshow_id'=>$slideshare_id,
+	);
+
+	$time=time();
+
+	$hash=sha1(get_option('slideshare_secret').strval($time));
+
+	$files=NULL;
+
+	$api_base='http://www.slideshare.net/api/2/get_slideshow';
+	$call=$api_base.'?api_key='.urlencode(get_option('slideshare_api_key')).'&ts='.urlencode(strval($time)).'&hash='.urlencode($hash);
+	$result=http_download_file($call,NULL,true,false,'ocPortal',$post,NULL,NULL,NULL,NULL,NULL,NULL,NULL,6.0,false,$files);
+	
+	if ((file_exists(get_file_base().'/data_custom/slideshare.log')) && (is_writeable(get_file_base().'/data_custom/slideshare.log')))
+	{
+		$log_file=fopen(get_file_base().'/data_custom/slideshare.log','at');
+		fwrite($log_file,date('Y-m-d H:i:s').': '.$call."\n");
+		fwrite($log_file,date('Y-m-d H:i:s').': '.$result."\n\n");
+	}
+
+	$matches=array();
+	preg_match('#<Embed>.*/(\w+\.swf\?.*)&quot;#U',$result,$matches);
+	$embed_key=html_entity_decode($matches[1],ENT_QUOTES,get_charset());
+
+	if (strpos($result,'<Status>0</Status')!==false) $embed_key='';
+	if (strpos($result,'<Status>1</Status')!==false) $embed_key='';
+
+	// Save
+
+	if (array_key_exists(0,$test))
+	{
+		$GLOBALS['SITE_DB']->query_update('slideshare_mapping',array('s_embed_key'=>$embed_key),array('s_slideshare_id'=>$slideshare_id),'',1);
+	} else
+	{
+		$GLOBALS['SITE_DB']->query_insert('slideshare_mapping',array(
+			's_slideshare_id'=>$slideshare_id,
+			's_local_file'=>$url,
+			's_embed_key'=>$embed_key,
+		));
+	}
+
+	$SLIDESHARE_DOC_IDS[$url]=$embed_key;
+	return $embed_key;
 }
 
 /**

--- sources/attachments.php	2011-03-13 13:30:50.529747000 +0000
+++ sources/attachments.php	2011-01-03 23:07:53.004767900 +0000
@@ -316,8 +316,8 @@
 		}
 		if (($attachment['a_width']=='') || ($attachment['a_height']==''))
 		{
-			$attachment['a_width']='240';
-			$attachment['a_height']='216';
+			$attachment['a_width']='600';
+			$attachment['a_height']='400';
 		}
 	}
 	$attachment['a_align']=array_key_exists('align',$attributes)?$attributes['align']:'left';
@@ -360,9 +360,9 @@

 			$temp_tpl=hyperlink($_url,($attachment['a_description']!='')?$attachment['a_description']:$attachment['a_original_filename'],true);
 			break;
-
+
 		default:
-			if (is_image($attachment['a_original_filename']))
+			if ((is_image($attachment['a_original_filename'])) && (is_image($attachment['a_url']))) // a_url must be checked as IIS does not support arbitrary file type URLs
 			{
 				if (($type=='inline') || ($type=='left_inline') || ($type=='right_inline')) $attachment['mini']='1';
 				require_code('images');
@@ -404,6 +404,26 @@
 				$temp_tpl=do_template('ATTACHMENT_MEDIA',map_keys_to_upper($attachment));
 				break;
 			}
+			elseif (in_array($mime_type,array('application/pdf','application/powerpoint','application/vnd.openxmlformats-officedocument.presentationml.presentation','application/vnd.oasis.opendocument.presentation')))
+			{
+				$temp_tpl=do_template('ATTACHMENT_PRESENTATION',map_keys_to_upper($attachment)+array('DOC_ID_URL'=>$attachment['a_url'],'DOC_ID_TITLE'=>$attachment['a_description'],'DOC_ID_ORIG_FILENAME'=>$attachment['a_original_filename']));
+				break;
+			}
+			elseif ((($mime_type=='application/x-tar') || ($mime_type=='application/zip')) && (addon_installed('galleries')))
+			{
+				require_code('galleries');
+				$myrow=array(
+					'id'=>$attachment['id'],
+					'url'=>$attachment['a_url'],
+					'thumb_url'=>$attachment['a_thumb_url'],
+					'comments'=>'',
+					'title'=>$attachment['a_description'],
+					'video_width'=>$attachment['a_width'],
+					'video_height'=>$attachment['a_height'],
+				);
+				$temp_tpl=show_video($myrow,$mime_type);
+				if (!$temp_tpl->is_empty()) break;
+			}
 			// Continues on, as it's not a media type...
 
 		case 'download':

--- sources/symbols.php	2011-03-13 13:31:05.472596000 +0000
+++ sources/symbols.php	2011-01-03 23:56:35.802942400 +0000
@@ -1669,6 +1901,99 @@
 				}
 				break;
 
+			case 'SLIDESHARE_DOC_ID':
+				require_code('images');
+				$value=slideshare_doc_id($param[0],$param[1],$param[2]);
+				break;
+				
+			case 'SWF_DOC':
+				if (array_key_exists(0,$param))
+				{
+					$filename=md5($param[0]);
+					$dir=get_custom_file_base().'/uploads/website_specific/';
+					if ((array_key_exists(1,$param)) && ($param[1]=='1'))
+					{
+						$filename.='/';
+						if (!file_exists($dir.$filename))
+						{
+							mkdir($dir.$filename,0777);
+							fix_permissions($dir.$filename,0777);
+							mkdir($dir.$filename.'swf',0777);
+							fix_permissions($dir.$filename.'swf',0777);
+							mkdir($dir.$filename.'txt',0777);
+							fix_permissions($dir.$filename.'txt',0777);
+							mkdir($dir.$filename.'xml',0777);
+							fix_permissions($dir.$filename.'xml',0777);
+							mkdir($dir.$filename.'pages',0777);
+							fix_permissions($dir.'pages',0777);
+							copy(get_custom_file_base().'/data_custom/pageflip/swf/Magazine.swf',$dir.$filename.'swf/Magazine.swf');
+							copy(get_custom_file_base().'/data_custom/pageflip/swf/Pages.swf',$dir.$filename.'swf/Pages.swf');
+							copy(get_custom_file_base().'/data_custom/pageflip/txt/Lang.txt',$dir.$filename.'txt/Lang.txt');
+						}
+
+						$dest_path_test=$dir.$filename.'pages/1.swf';
+						$dest_path=$dir.$filename.'pages/%.swf';
+					} else
+					{
+						$dest_path_test=$dir.$filename.'.swf';
+						$dest_path=$dir.$filename.'.swf';
+					}
+					if (!file_exists($dest_path_test))
+					{
+						$place='';
+						if (file_exists('/usr/local/bin/pdf2swf')) $place='/usr/local/bin/';
+						if (file_exists('C:\\Program Files (x86)\\SWFTools\\pdf2swf.exe')) $place='C:\\Program Files (x86)\\SWFTools\\';
+						if (strpos(strtolower(PHP_OS),'win')!==false)
+							if (file_exists(get_file_base().'/data_custom/pdf2swf.exe')) $place=get_file_base().DIRECTORY_SEPARATOR.'data_custom'.DIRECTORY_SEPARATOR;
+						$command='"'.$place.'pdf2swf" '.escapeshellarg(get_custom_file_base().'/'.rawurldecode($param[0])).' -o '.str_replace('PERCENT','%',escapeshellarg(str_replace('%','PERCENT',$dest_path)));
+						shell_exec($command);
+					}
+					if ((array_key_exists(1,$param)) && ($param[1]=='1'))
+					{
+						$new='';
+						$i=1;
+						while (file_exists($dir.$filename.'pages/'.strval($i).'.swf'))
+						{
+							$new.='<page src="pages/'.strval($i).'.swf" />';
+							$i++;
+						}
+						$new=str_replace('<page src="pages/01.jpg"/>',$new,file_get_contents(get_custom_file_base().'/data_custom/pageflip/xml/Pages.xml',FILE_TEXT));
+						$myfile=fopen($dir.$filename.'xml/Pages.xml','wt');
+						fwrite($myfile,$new);
+						fclose($myfile);
+
+						$value=get_custom_base_url().'/uploads/website_specific/'.$filename;
+					} else
+					{
+						$value=get_custom_base_url().'/uploads/website_specific/'.$filename.'.swf';
+					}
+				}
+				break;
+
+			case 'IS_VIDEO':
+				if (array_key_exists(0,$param))
+				{
+					require_code('images');
+					$value=is_video($param[0])?'_true':'_false';
+				}
+				break;
+
+			case 'IS_IMAGE':
+				if (array_key_exists(0,$param))
+				{
+					require_code('images');
+					$value=is_image($param[0])?'_true':'_false';
+				}
+				break;
+
+			case 'IS_PRESENTATION':
+				if (array_key_exists(0,$param))
+				{
+					require_code('images');
+					$value=is_presentation($param[0])?'_true':'_false';
+				}
+				break;
+
 			case 'SSW':
 				$value=(get_option('ssw')=='1')?'_true':'_false';
 				break;
--- sources/mime_types.php	2011-03-13 13:31:00.120408800 +0000
+++ sources/mime_types.php	2010-09-30 22:05:58.351239000 +0100
@@ -28,6 +28,10 @@
 {
 	$mime_types=array(
 
+		// Archive
+		'tar'=>'application/x-tar',
+		'zip'=>'application/zip',
+
 		// Plain text
 		'1st'=>'text/plain',
 		'txt'=>'text/plain',
@@ -58,7 +62,11 @@
 
 		// Presentations/Animations/3D
 		'ppt'=>'application/powerpoint',
+		'pot'=>'application/powerpoint',
+		'pps'=>'application/powerpoint',
 		'pptx'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+		'potx'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+		'ppsx'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation',
 		'svg'=>'application/octet-stream', // to prevent XSS	//'image/svg+xml',
 		'wrl'=>'model/vrml',
 		'vrml'=>'model/vrml',
--- lang/EN/global.ini	2011-03-13 13:30:40.191330300 +0000
+++ lang/EN/global.ini	2010-12-01 10:47:59.444248900 +0000
@@ -150,5 +150,6 @@
 GRAPH=Graph
 GUIDES=Guides
 ANIMATION=You need <a target="_blank" title="(this link will open in a new window)" href="http://get.adobe.com/flashplayer/">Adobe Flash Player</a> to view this video/animation.
+PRESENTATION=Presentation
 MEDIA=Media
 VIDEO=Video
--- sources/galleries.php	2011-03-13 13:30:57.827341800 +0000
+++ sources/galleries.php	2011-01-11 01:58:35.446558200 +0000
@@ -667,4 +667,171 @@
 
 	return $use_compound_list?array($children,$compound_list):$children;
 }
 
+/**
+ * Show a video.
+ *
+ * @param  array			The video record
+ * @param  ?string		The mime type (NULL: work out from URL)
+ * @return tempcode		Rendered video
+ */
+function show_video($myrow,$mime_type=NULL)
+{
+	$url=$myrow['url'];
+	if (url_is_local($url)) $url=get_custom_base_url().'/'.$url;
+
+	$thumb_url=$myrow['thumb_url'];
+	if (url_is_local($thumb_url)) $thumb_url=get_custom_base_url().'/'.$thumb_url;
+
+	// Comments
+	$comments=is_integer($myrow['comments'])?get_translated_tempcode($myrow['comments']):$myrow['comments'];
+
+	$extension=get_file_extension($url);
+	require_code('mime_types');
+	if (is_null($mime_type))
+		$mime_type=get_mime_type($extension);
+	if (($myrow['video_width']!=600) && ($myrow['video_width']!=0) && ($myrow['video_height']!=0))
+	{
+		$myrow['video_height']=intval(600.0*floatval($myrow['video_height'])/floatval($myrow['video_width']));
+		$myrow['video_width']=600;
+	}
+	$tpl_map=array('ID'=>strval($myrow['id']),'LENGTH'=>array_key_exists('video_length',$myrow)?strval($myrow['video_length']):'','TITLE'=>$myrow['title'],'DESCRIPTION'=>$comments,'THUMB_URL'=>$thumb_url,'URL'=>$url,'WIDTH'=>strval($myrow['video_width']),'HEIGHT'=>strval($myrow['video_height']),'MIME_TYPE'=>$mime_type);
+	if (substr($mime_type,0,6)=='image/')
+	{
+		$tpl='GALLERY_VIDEO_TAR';
+		$tpl_map['CONTENT']=array();
+		if (url_is_local($myrow['url']))
+			$myrow['url']=get_custom_base_url().'/'.$myrow['url'];
+		$tpl_map['CONTENT'][]=array('DESCRIPTION'=>$comments,'ORIG_NAME'=>basename($myrow['url']),'IMG_URL'=>$myrow['url']);
+	} else
+	{
+		if ($extension=='swf')
+		{
+			$mime_type='application/x-shockwave-flash';
+			$tpl='GALLERY_SWF';
+		}
+		else
+		{
+			switch ($mime_type)
+			{
+				case 'application/pdf':
+				case 'application/powerpoint':
+				case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
+				case 'application/vnd.oasis.opendocument.presentation':
+					$tpl='GALLERY_VIDEO_PRESENTATION';
+					$tpl_map+=array('DOC_ID_URL'=>$url,'DOC_ID_TITLE'=>html_entity_decode(strip_tags($comments->evaluate()),ENT_QUOTES,get_charset()),'DOC_ID_ORIG_FILENAME'=>basename($url));
+					break;
+		
+				case 'video/x-flv':
+				case 'video/mp4':
+				case 'video/webm':
+					if (addon_installed('jwplayer'))
+					{
+						$tpl='GALLERY_VIDEO_FLV';
+						break;
+					}
+				case 'video/quicktime':
+					$tpl='GALLERY_VIDEO_QT';
+					break;
+				case 'audio/x-pn-realaudio':
+					$tpl='GALLERY_VIDEO_RM';
+					break;
+				case 'application/zip':
+					$tpl='GALLERY_VIDEO_TAR';
+					require_code('images');
+					if ((!function_exists('zip_open')) && (get_option('unzip_cmd')=='')) warn_exit(do_lang_tempcode('ZIP_NOT_ENABLED'));
+					if (!function_exists('zip_open'))
+					{
+						require_code('m_zip');
+						$mzip=true;
+					} else $mzip=false;
+					$path=get_custom_file_base().'/'.rawurldecode($myrow['url']);
+					$tpl_map['CONTENT']=array();
+					$myfile=zip_open($path);
+					if ($myfile!==false)
+					{
+						while (false!==($entry=zip_read($myfile)))
+						{
+							// Load in file
+							zip_entry_open($myfile,$entry);
+	
+							$_file=zip_entry_name($entry);
+	
+							if ((is_image($_file)) && (substr($_file,0,1)!='.'))
+							{
+								$out_path=get_custom_file_base().'/uploads/auto_thumbs/'.md5($path.'/'.$_file).'.'.get_file_extension($_file);
+								if (!file_exists($out_path))
+								{
+									$outfile=fopen($out_path,'wb');
+									$more=mixed();
+									do
+									{
+										$more=zip_entry_read($entry);
+										if (fwrite($outfile,$more)<strlen($more)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
+									}
+									while (($more!==false) && ($more!=''));
+									fclose($outfile);
+									fix_permissions($path);
+									sync_file($path);
+								}
+	
+								$meta_data=function_exists('exif_read_data')?exif_read_data($out_path):NULL;
+								$comments=isset($meta_data['COMPUTED']['UserComment'])?$meta_data['COMPUTED']['UserComment']:'';
+
+								$tpl_map['CONTENT'][]=array('DESCRIPTION'=>$comments,'ORIG_NAME'=>$_file,'IMG_URL'=>get_custom_base_url().'/uploads/auto_thumbs/'.md5($path.'/'.$_file).'.'.get_file_extension($_file));
+							}
+	
+							zip_entry_close($entry);
+						}
+	
+						zip_close($myfile);
+					}
+
+					if (count($tpl_map['CONTENT'])==0) return new ocp_tempcode();
+					global $M_SORT_KEY;
+					$M_SORT_KEY='ORIG_NAME';
+					usort($tpl_map['CONTENT'],'multi_sort');
+					break;
+				case 'application/x-tar':
+					$tpl='GALLERY_VIDEO_TAR';
+					require_code('tar');
+					require_code('images');
+					$path=get_custom_file_base().'/'.rawurldecode($myrow['url']);
+					$tarfile=tar_open($path,'rb');
+					$dir=tar_get_directory($tarfile);
+					$tpl_map['CONTENT']=array();
+					foreach ($dir as $d)
+					{
+						if ((is_image($d['path'])) && (substr($d['path'],0,1)!='.'))
+						{
+							$out_path=get_custom_file_base().'/uploads/auto_thumbs/'.md5($path.'/'.$d['path']).'.'.get_file_extension($d['path']);
+							if (!file_exists($out_path))
+							{
+								$file=tar_get_file($tarfile,$d['path'],true);
+								$outfile=fopen($out_path,'wb');
+								if (fwrite($outfile,$file['data'])<strlen($file['data'])) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
+								fclose($outfile);
+								fix_permissions($path);
+								sync_file($path);
+							}
+
+							$meta_data=function_exists('exif_read_data')?exif_read_data($out_path):NULL;
+							$comments=isset($meta_data['COMPUTED']['UserComment'])?$meta_data['COMPUTED']['UserComment']:'';
+
+							$tpl_map['CONTENT'][]=array('DESCRIPTION'=>$comments,'ORIG_NAME'=>$d['path'],'IMG_URL'=>get_custom_base_url().'/uploads/auto_thumbs/'.md5($path.'/'.$d['path']).'.'.get_file_extension($d['path']));
+						}
+					}
+					tar_close($tarfile);
+
+					if (count($tpl_map['CONTENT'])==0) return new ocp_tempcode();
+					global $M_SORT_KEY;
+					$M_SORT_KEY='ORIG_NAME';
+					usort($tpl_map['CONTENT'],'multi_sort');
+					break;
+				default:
+					$tpl='GALLERY_VIDEO_GENERAL';
+			}
+		}
+	}
+	return do_template($tpl,$tpl_map);
+}


--- site/pages/modules/galleries.php	2011-03-13 13:30:16.879401800 +0000
+++ site/pages/modules/galleries.php	2010-12-01 10:48:00.391303000 +0000
@@ -667,51 +702,6 @@
 				$thumb_url=$row['thumb_url'];
 				if (url_is_local($thumb_url)) $thumb_url=get_custom_base_url().'/'.$thumb_url;
 				$url=$row['url'];
 				$full_url=url_is_local($url)?(get_custom_base_url().'/'.$url):$url;
-				$extension=get_file_extension($url);
-
-				if ($extension=='swf')
-				{
-					$mime_type='application/x-shockwave-flash';
-					$tpl='GALLERY_SWF';
-				}
-				else
-				{
-					require_code('mime_types');
-					$mime_type=get_mime_type($extension);
-					switch ($mime_type)
-					{
-						case 'video/quicktime':
-							$tpl='GALLERY_VIDEO_QT';
-							break;
-						case 'audio/x-pn-realaudio':
-							$tpl='GALLERY_VIDEO_RM';
-							break;
-						case 'video/x-flv':
-						case 'video/mp4':
-						case 'video/webm':
-							if (addon_installed('jwplayer'))
-							{
-								$tpl='GALLERY_VIDEO_FLV';
-								break;
-							}
-						default:
-							$matches=array();
-							$ve_hooks=find_all_hooks('systems','video_embed');
-							foreach (array_keys($ve_hooks) as $ve_hook)
-							{
-								require_code('hooks/systems/video_embed/'.$ve_hook);
-								$ve_ob=object_factory('Hook_video_embed_'.$ve_hook);
-								$ve_test=$ve_ob->get_template_name_and_id($url);
-								if (!is_null($ve_test))
-								{
-									list($tpl,$url)=$ve_test;
-									break 2;
-								}
-							}
-
-							$tpl='GALLERY_VIDEO_GENERAL';
-					}
-				}
-				$video_player=do_template($tpl,array('THUMB_URL'=>$thumb_url,'URL'=>$full_url,'LENGTH'=>strval($row['video_length']),'WIDTH'=>strval($row['video_width']),'HEIGHT'=>strval($row['video_height']),'MIME_TYPE'=>$mime_type));
+				$video_player=$video=show_video($row);
 				$view_url=build_url(array('page'=>'_SELF','type'=>'video','id'=>$row['id'],'wide'=>1),'_SELF');
@@ -1090,50 +1132,6 @@
 		$edit_date=is_null($myrow['edit_date'])?'':get_timezoned_date($myrow['edit_date']);
 
 		// Video HTML
-		$extension=get_file_extension($url);
-		require_code('mime_types');
-		$mime_type=get_mime_type($extension);
-		if ($extension=='swf')
-		{
-				$mime_type='application/x-shockwave-flash';
-				$tpl='GALLERY_SWF';
-		}
-		else
-		{
-			switch ($mime_type)
-			{
-				case 'video/quicktime':
-					$tpl='GALLERY_VIDEO_QT';
-					break;
-				case 'audio/x-pn-realaudio':
-					$tpl='GALLERY_VIDEO_RM';
-					break;
-				case 'video/x-flv':
-				case 'video/mp4':
-				case 'video/webm':
-					if (addon_installed('jwplayer'))
-					{
-						$tpl='GALLERY_VIDEO_FLV';
-						break;
-					}
-				default:
-					$matches=array();
-					$ve_hooks=find_all_hooks('systems','video_embed');
-					foreach (array_keys($ve_hooks) as $ve_hook)
-					{
-						require_code('hooks/systems/video_embed/'.$ve_hook);
-						$ve_ob=object_factory('Hook_video_embed_'.$ve_hook);
-						$ve_test=$ve_ob->get_template_name_and_id($url);
-						if (!is_null($ve_test))
-						{
-							list($tpl,$url)=$ve_test;
-							break 2;
-						}
-					}
-
-					$tpl='GALLERY_VIDEO_GENERAL';
-			}
-		}
-		$video=do_template($tpl,array('THUMB_URL'=>$thumb_url,'URL'=>$url,'LENGTH'=>strval($myrow['video_length']),'WIDTH'=>strval($myrow['video_width']),'HEIGHT'=>strval($myrow['video_height']),'MIME_TYPE'=>$mime_type));
+		$video=show_video($myrow);

		$map=array('cat'=>$cat);
--- cms/pages/modules/cms_galleries.php	2011-03-13 13:30:16.879401800 +0000
+++ cms/pages/modules/cms_galleries.php	2010-12-01 10:48:00.391303000 +0000
@@ -103,6 +105,10 @@
 		{
 			$this->alt_aed_module->add_text->attach(paragraph(do_lang_tempcode('ALSO_AUDIO')));
 		}
+		if (get_option('allow_slideshare')=='1')
+		{
+			$this->alt_aed_module->add_text->attach(paragraph(do_lang_tempcode('ALSO_PRESENTATION')));
+		}
 
 		// Decide what to do
 		if ($type=='misc') return $this->misc();

--- lang/EN/galleries.ini	2011-03-13 13:30:40.150327900 +0000
+++ lang/EN/galleries.ini	2010-12-01 10:47:59.449249200 +0000
@@ -44,7 +44,7 @@
 TEASER=Teaser description
 DESCRIPTION_TEASER=Information about the gallery shown in the gallery teaser block; one use for that block is for those who may not have access.
 SUBGALLERY_BITS={1}&nbsp;{1|subgallery|subgalleries}
-_SUBGALLERY_BITS={1}&nbsp;{1|image|images}, {2}&nbsp;{2|video|videos}
+_SUBGALLERY_BITS={3}&nbsp;{3|entry|entries}
 VIDEO_DETAILS=Video details
 MAXIMUM_IMAGE_SIZE=Maximum image size
 CONFIG_OPTION_maximum_image_size=The maximum width or height an image can be in pixels; this only works if the GD image library is enabled. If the image is too big, it will be resized.
@@ -63,12 +63,13 @@
 DEFAULT_VIDEO_HEIGHT=Default video height
 CONFIG_OPTION_default_video_width=The default width in pixels at which a video will be shown if it is not specified.
 CONFIG_OPTION_default_video_height=The default height in pixels at which a video will be shown if it is not specified.
-DESCRIPTION_VIDEO_WIDTH=The width in pixels at which the video will be displayed. This is only necessary for some video types. (May be auto-detected for <kbd>wmv/avi/mov/mp4</kbd>). You may leave this blank for an audio file.
-DESCRIPTION_VIDEO_HEIGHT=The height in pixels at which the video will be displayed. This is only necessary for some video types. (May be auto-detected for <kbd>wmv/avi/mov/mp4</kbd>). You may leave this blank for an audio file.
+DESCRIPTION_VIDEO_WIDTH=The width in pixels at which the video will be displayed. This is only necessary for some video types. (May be auto-detected for <kbd>wmv/avi/mov/mp4</kbd>). You may leave this blank for an audio/presentation file.
+DESCRIPTION_VIDEO_HEIGHT=The height in pixels at which the video will be displayed. This is only necessary for some video types. (May be auto-detected for <kbd>wmv/avi/mov/mp4</kbd>). You may leave this blank for an audio/presentation file.
 VIEW_VIDEO=View video
+_VIEW_VIDEO=Video: {1}
 VIDEOS=Videos
-_VIDEO_LENGTH=Video length: {1} {1|second|seconds}
-VIDEO_LENGTH=Video length
+_VIDEO_LENGTH=Media length: {1} {1|second|seconds}
+VIDEO_LENGTH=Media length
 DESCRIPTION_VIDEO_LENGTH=The play length of the video in seconds. (May be auto-detected for <kbd>ram/wmv/avi/mov/mp4</kbd>).
 ACCEPT_IMAGES=Accept images
 ACCEPT_VIDEOS=Accept videos
@@ -98,11 +99,13 @@
 DELETE_OWN_MEDIA=Delete own image/video
 BYPASS_VALIDATION_MEDIA=Bypass image/video validation
 ADD_VIDEO=Add video
-ALSO_AUDIO=Please note that you may upload audio files instead of video files if you wish.
+ALSO_AUDIO=You may upload audio files instead of video files if you wish.
+ALSO_PRESENTATION=You may also upload presentation files instead of video files if you wish (e.g. <acronym title="PowerPoinT">PPT</acronym> files). Or, you may upload ZIP files full of images of individual images.
 EDIT_VIDEO=Edit video
 DELETE_VIDEO=Delete video
 GALLERIES=Galleries
 VIEW_IMAGE=View image
+_VIEW_IMAGE=Image: {1}
 VIEWING_GALLERY_ENTRY=&laquo; <strong>{1}</strong> of <strong>{2}</strong> &raquo;
 PT_may_download_gallery=Download the contents of a gallery as an archive file
 DOWNLOAD_GALLERY_CONTENTS=Download the contents of the gallery
@@ -121,7 +124,7 @@
 PT_high_personal_gallery_limit=Have more entries in their personal galleries
 PT_no_personal_gallery_limit=Have any number of entries in their personal galleries
 TOO_MANY_GALLERY_IMAGES=Sorry, adding more images to this gallery would cause your personal limit to be exceeded.
-TOO_MANY_GALLERY_VIDEOS=Sorry, adding more videos/audio to this gallery would cause your personal limit to be exceeded.
+TOO_MANY_GALLERY_VIDEOS=Sorry, adding more videos/audio/presentations to this gallery would cause your personal limit to be exceeded.
 X_ENTRIES_REMAINING=You may make {1} more entries in this gallery.
 NEXT_ITEM_add_one_image=Add image
 NEXT_ITEM_add_one_video=Add video
@@ -171,3 +174,6 @@
 CONFIG_OPTION_ffmpeg_path=The path to the ffmpeg tool, with a trailing slash. E.g. <kbd>/usr/bin/</kbd>. Leave this blank if there should be no transcoding to FLV/MP3 files.
 CONFIG_OPTION_video_width_setting=The width video should be transcoded to.
 CONFIG_OPTION_video_height_setting=The height video should be transcoded to.
+ALL_IN_GALLERY=Everything in {1}
+UPLOAD_YOUR_CLIP=upload your clip
+TRANSCODING_SERVER=Transcoding media files server






create_video_thumb needs...
if (substr($src_file,-4)=='.zip')
{
	$out_url='';
	if ((!function_exists('zip_open')) && (get_option('unzip_cmd')=='')) warn_exit(do_lang_tempcode('ZIP_NOT_ENABLED'));
	if (!function_exists('zip_open'))
	{
		require_code('m_zip');
		$mzip=true;
	} else $mzip=false;
	$myfile=zip_open($src_file);
	if ($myfile!==false)
	{
		while (false!==($entry=zip_read($myfile)))
		{
			// Load in file
			zip_entry_open($myfile,$entry);

			$_file=zip_entry_name($entry);

			if ((is_image($_file)) && (substr($_file,0,1)!='.'))
			{
				$out_path=get_custom_file_base().'/uploads/galleries/'.md5($src_file.'/'.$d['path']).'.'.get_file_extension($d['path']);
				$out_url='uploads/galleries/'.rawurlencode(md5($src_file.'/'.$d['path']).'.'.get_file_extension($d['path']));

				$outfile=fopen($out_path,'wb');
				$more=mixed();
				do
				{
					$more=zip_entry_read($entry);
					if (fwrite($outfile,$more)<strlen($more)) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
				}
				while (($more!==false) && ($more!=''));
				fclose($outfile);
				fix_permissions($path);
				sync_file($path);

				break;
			}

			zip_entry_close($entry);
		}

		zip_close($myfile);

		return $out_url;
	}
}

if (substr($src_file,-4)=='.tar')
{
	$out_url='';
	require_code('tar');
	$tarfile=tar_open($src_file,'rb');
	$dir=tar_get_directory($tarfile);
	foreach ($dir as $d)
	{
		if ((is_image($d['path'])) && (substr($d['path'],0,1)!='.'))
		{
			$out_path=get_custom_file_base().'/uploads/galleries/'.md5($src_file.'/'.$d['path']).'.'.get_file_extension($d['path']);
			$out_url='uploads/galleries/'.rawurlencode(md5($src_file.'/'.$d['path']).'.'.get_file_extension($d['path']));

			$file=tar_get_file($tarfile,$d['path'],true);
			$outfile=fopen($out_path,'wb');
			if (fwrite($outfile,$file['data'])<strlen($file['data'])) warn_exit(do_lang_tempcode('COULD_NOT_SAVE_FILE'));
			fclose($outfile);
			fix_permissions($path);
			sync_file($path);
			break;
		}
	}
	tar_close($tarfile);

	return $out_url;
}

slideshare.diff (39,666 bytes)

Chris Graham

2020-06-25 01:19

administrator   ~0006612

There's this Open Source PDF flipbook reader:
https://github.com/erayakartuna/pdf-flipbook

However, it is unmaintained. I updated it a bit for a client project, only to find it fundamentally cannot support hyperlinks in PDF files.

DearFlip (https://dearflip.com/) aka dflip, is a very nice solution that does support hyperlinks, but is commercial.

pdf.js is a nice reader, but doesn't support flipbook-style reading. The above two projects actually use it internally.

Issue History

Date Modified Username Field Change
2016-11-21 14:35 Chris Graham New Issue
2016-11-21 14:35 Chris Graham File Added: slideshare.diff
2020-06-25 01:19 Chris Graham Note Added: 0006612