Creating/Saving an inline base64 encoded image - php

I am trying to create & save images from data in an email from the base64 data of an actual image that was in the html body that appears inline such as:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAE==">
But i'm trying to create them sequentially, as there could be more than one image tag in the html body, where the variable $html_part is the html body of the email.
I just need some assistance in coming to a solution on what i'm doing wrong.
$img_tags = preg_match('/<img\s+(.*)>/', $html_part, $num_img_tags);
$num_img_tags = count($num_img_tags);
echo $html_part;
for ($i = 1; $i <= $num_img_tags; $i++) {
preg_match('/<img\s+(.*)\s+src="data:image\/(.*);(.*),(.*)"\s+(.*)>/i', $html_part, $srcMatch);
{
foreach($srcMatch[4] as $im_data)
{
$ufname = "image0".$num_img_tags.".jpg";
echo "<h1>$ufname</h1>";
$im_data = base64_decode($im_data);
$im = imagecreatefromstring($im_data);
if ($im !== false) {
header('Content-Type: image/jpeg');
imagejpeg($im, $ufname);
imagedestroy($im);
}
else {
echo 'An error occurred.';
}
}
}
}

Your code is impossible - you cannot do a header() call after you've performed ANY output. You can also not output multiple images in the same 'document'. You also cannot output html (the <h1> stuff), images (header('Content-type:...'), etc... all within the same document.
As well, parsing/processing HTML with regexes is dangerous. A single malformation of the source document and your regexes will happily feast on garbage and produce garbage for you. Do not use regexes on html... every time you do, Alan Turing kills a kitten. Use a DOM parser instead.

Pretty sure you want to use a preg_match_all, not a preg_match
http://php.net/manual/en/function.preg-match-all.php
Also, solution using the above.
<?php
$html_part=<<<END
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAVFBMVEWcZjTcViTMuqT8/vzcYjTkhhTkljT87tz03sRkZmS8mnT03tT89vTsvoTk1sz86uTkekzkjmzkwpT01rTsmnzsplTUwqz89uy0jmzsrmTknkT0zqT3X4fRAAAAbklEQVR4XnXOVw6FIBBAUafQsZfX9r/PB8JoTPT+QE4o01AtMoS8HkALcH8BGmGIAvaXLw0wCqxKz0Q9w1LBfFSiJBzljVerlbYhlBO4dZHM/F3llybncbIC6N+70Q7OlUm7DdO+gKs9gyRwdgd/LOcGXHzLN5gAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAVFBMVEWcZjTcViTMuqT8/vzcYjTkhhTkljT87tz03sRkZmS8mnT03tT89vTsvoTk1sz86uTkekzkjmzkwpT01rTsmnzsplTUwqz89uy0jmzsrmTknkT0zqT3X4fRAAAAbklEQVR4XnXOVw6FIBBAUafQsZfX9r/PB8JoTPT+QE4o01AtMoS8HkALcH8BGmGIAvaXLw0wCqxKz0Q9w1LBfFSiJBzljVerlbYhlBO4dZHM/F3llybncbIC6N+70Q7OlUm7DdO+gKs9gyRwdgd/LOcGXHzLN5gAAAAASUVORK5CYII=">
END;
preg_match_all('/<img.*?src="data:image\/.*;.*,(.*)".*?>/i', $html_part, $img_tags, PREG_PATTERN_ORDER);
echo $html_part;
$img_num = 0;
foreach($img_tags[1] as $im_data)
{
$ufname = "image0".$img_num.".jpg";
echo "<h1>$ufname</h1>";
$im_data = base64_decode($im_data);
$im = imagecreatefromstring($im_data);
if ($im !== false) {
imagejpeg($im, $ufname);
imagedestroy($im);
}
else {
echo 'An error occurred.';
}
$img_num++;
}

Related

What is causing my PHP page to render html tags as text (and what can I do to fix it)?

I have the following PHP code: When it is commented out (as it is now) from just after the comment // ... more stuff in here to the end of that comment block, my page renders html from that 2nd php block as expected as in this screenshot.
If I uncomment that block it renders like the screenshot after the code below which is not what I want (I want the rendered html as in the first screenshot). The only thing not showing in my comment block is a function call that curls a webpage, parses html with DomXNode types of things, and returns an array with 3 elements. How can I get the original rendering of the html back and what am I possibly doing that is ruining that for me? I tried echo instead of print and that makes no difference.
I honestly did search for the answer on here and found lots of pages describing how do do just the opposite of what I want so please be gentle with me. I was surprised that I couldn't find a similar question and I know there has to be an easy answer here. Thanks!
<?php
// ... more stuff in here
/*
include("../../includes/curl_fx.php");
if ($doAppend === "parcel") {
$lines = explode(PHP_EOL, $Data);
foreach($lines as $line) {
if(strpos($line, "http") > 0) {
$start = stripos(strval($line), "http");
$fullLength = strlen($line);
$urlLength = ($fullLength - $start);
$fullUrl = substr($line, $start, $urlLength);
$arraySDAT = getSDAT($fullUrl);
$line .= ", " . $arraySDAT[0] . ", " . $arraySDAT[1] . ", " . $arraySDAT[2] . "\n";
fwrite($Handle, $line);
}
}
}
*/
?>
<?php
if ($DataAdded === true) {
print "<h2>YourFile.txt</h2>Data has been added.<br />Close this window or tab to return to the web map.<br />";
} else {
print "Data may not have been added. Check the file.<br />";
}
fclose($Handle);
print $doAppendAnswer;
print "<br />";
?>
EDIT: Here is the function.
<?php
function getSDAT ($fullUrl="") {
$ch = curl_init($fullUrl);
if (! $ch) {
die( "Cannot allocate a new PHP-CURL handle" );
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
header("Content-type: text");
curl_close($ch);
libxml_use_internal_errors(true);
libxml_clear_errors();
$doc = DOMDocument::loadHTML($data);
$xpath = new DOMXPath($doc);
$ownName1query = '//table/tr/td/span[#id="MainContent_MainContent_cphMainContentArea_ucSearchType_wzrdRealPropertySearch_ucDetailsSearch_dlstDetaisSearch_lblOwnerName_0"][#class="text"]';
$ownName2query = '//table/tr/td/span[#id="MainContent_MainContent_cphMainContentArea_ucSearchType_wzrdRealPropertySearch_ucDetailsSearch_dlstDetaisSearch_lblOwnerName2_0"][#class="text"]';
$ownAddrquery = '//table/tr/td/span[#id="MainContent_MainContent_cphMainContentArea_ucSearchType_wzrdRealPropertySearch_ucDetailsSearch_dlstDetaisSearch_lblMailingAddress_0"][#class="text"]';
$entries = $xpath->query($ownName1query);
foreach($entries as $entry) {
$ownname1 = $entry->nodeValue;
}
$entries = $xpath->query($ownName2query);
foreach($entries as $entry) {
$ownname2 = $entry->nodeValue;
}
$entries = $xpath->query($ownAddrquery);
$pattern = '#<br\s*/?>#i';
$replacement = ", ";
$i=0;
foreach($entries as $entry) {
$ownAddr = $entry->nodeValue;
if(!$entry->childNodes == 0) {
$ownAddr = $doc->saveHTML($entry);
}
$ownAddr2 = preg_replace($pattern, $replacement, $ownAddr, 15, $count); // replace <br/> with a comma
$ownAddr3 = strip_tags($ownAddr2);
}
return array($ownname1, $ownname2, $ownAddr3);
}
Your problem is:
header("Content-type: text");
Just remove that. Why is it there?
As mentioned, it's the header which is causing you a problem. You see the header decides the type of content that the current document should have or how the current document should behave - an information that is usually found in the < head >...< /head > part of an HTML. You can use it for declaring the content type, controlling the cache, redirecting, and etc.
When you use header("Content-type: text"), you are deciding that the content of the current document "yourdocument.php" would be a text instead of the default which is HTML.
header("Content-type: text/html");
echo "<html>This would make mypage.php behave as an HTML</html>";
// This is usually unnecessary since text/html is already the default header
header("Content-type: text/javascript");
echo "this would make mypage.php behave as a javascript";
header("Content-type: text/css");
echo "this would make mypage.php behave as a CSS";
header('Content-type: image/jpeg');
readfile("source/to/my/file.jpg");
// this would make mypage.php display file.jpg and act as a jpg
header('Content-type: image/png');
readfile("source/to/my/file.png");
// this would make mypage.php display file.png and act as a png
header('Content-type: image/gif');
readfile("source/to/my/file.gif");
// this would make mypage.php display file.gif and act as a gif
header('Content-type: image/x-icon');
readfile("source/to/my/file.ico");
// this would make mypage.php display file.ico and act as an icon
header('Content-type: image/x-win-bitmap');
readfile("source/to/my/file.cur");
// this would make mypage.php display file.cur and act as a cursor

php barcode - display multiple barcode in single page

I created a php page that print the barcode. Just to view it before i print it on an A4. Still in testing phase. The codes are as below.
<?php
include('include/conn.php');
include('include/Barcode39.php');
$sql="select * from barcode where b_status = 'NOT-PRINTED'";
$result=mysqli_query($conn,$sql);
echo mysqli_num_rows($result);
$i=0;
while($row=mysqli_fetch_assoc($result)){
$acc_no = $row["b_acc_no_code"];
$bc = new Barcode39($row["b_acc_no_code"]);
echo $bc->draw();
$bc->draw($acc_no.$i.".jpg");
echo '<br /><br />';
$i++;
}
?>
Without the while loop, it can be printed, but only one barcode. How to make it generate, for example in the database have 5 values, it will print 5 barcode in the same page. Thanks in advance
Try to use another bar code source. Because It is generate only one bar code per page. Can't able to create multiple bar code per page.
I know this is an older post but comes up in searches so is probably worth replying to.
I have successfully used the Barcode39 to display multiple barcodes. The trick is to get base64 data from the class and then display the barcodes in separate HTML tags.
The quickest way to do this is to add a $base64 parameter to the draw() method:
public function draw($filename = null, $base64 = false) {
Then, near the end of the draw() method, modify to buffer the imagegif() call and return the output in base64:
// check if writing image
if ($filename) {
imagegif($img, $filename);
}
// NEW: Return base 64 for the barcode image
else if ($base64) {
ob_start();
imagegif($img);
$image_data = ob_get_clean();
imagedestroy($img);
return base64_encode($image_data);
}
// display image
else {
header("Content-type: image/gif");
imagegif($img);
}
Finally, to display multiples from the calling procedure, construct the image HTML in the loop and display:
// assuming everything else has been set up, end with this...
$base64 = $barcode->draw('', true); // Note the second param is set for base64
$html = '';
for ($i = 0; $i < $numBarcodes; $i++) {
$html .= '<img src="data:image/gif;base64,'.$base64.'">';
}
die('<html><body>' . $html . '</body></html>');
I hope this helps anyone else facing this challenge.

Simple-html-dom skips attributes

I am trying to parse html page of Google play and getting some information about apps. Simple-html-dom works perfect, but if page contains code without spaces, it completely ingnores attributes. For instance, I have html code:
<div class="doc-banner-icon"><img itemprop="image"src="https://lh5.ggpht.com/iRd4LyD13y5hdAkpGRSb0PWwFrfU8qfswGNY2wWYw9z9hcyYfhU9uVbmhJ1uqU7vbfw=w124"/></div>
As you can see, there is no any spaces between image and src, so simple-html-dom ignores src attribute and returns only <img itemprop="image">. If I add space, it works perfectly. To get this attribute I use the following code:
foreach($html->find('div.doc-banner-icon') as $e){
foreach($e->find('img') as $i){
$bannerIcon = $i->src;
}
}
My question is how to change this beautiful library to get full inner text of this div?
I just create function which adds neccessary spaces to content:
function placeNeccessarySpaces($contents){
$quotes = 0; $flag=false;
$newContents = '';
for($i=0; $i<strlen($contents); $i++){
$newContents.=$contents[$i];
if($contents[$i]=='"') $quotes++;
if($quotes%2==0){
if($contents[$i+1]!== ' ' && $flag==true) {
$newContents.=' ';
$flag=false;
}
}
else $flag=true;
}
return $newContents;
}
And then use it after file_get_contents function. So:
$contents = file_get_contents($url, $use_include_path, $context, $offset);
$contents = placeNeccessarySpaces($contents);
Hope it helps to someone else.

PHP file_get_contents

I'm looking to create a PHP script where, a user will provide a link to a webpage, and it will get the contents of that webpage and based on it's contents, parse the contents.
For example, if a user provides a YouTube link:
http://www.youtube.com/watch?v=xxxxxxxxxxx
Then, it will grab the basic information about that video (thumbnail, embed code?)
Or they might provide a vimeo link:
http://www.vimeo.com/xxxxxx
Or even if they were to provide any link, without a video attached, such as:
http://www.google.com/
And it could grab just the page Title or some meta content.
I'm thinking I'd have to use file_get_contents, but I'm not exactly sure how to use it in this context.
I'm not looking for someone to write the entire code, but perhaps provide me with some tools so that I can accomplish this.
You can use either the curl or the http library. You send a http request, and can use the library to get the information from the http response.
I know this question is quite old, but I'll answer just in case someone hits it looking for the same thing.
Use oEmbed (http://oembed.com/) for YouTube, Vimeo, Wordpress, Slideshare, Hulu, Flickr and many other services. If not in the list or you want to make it more precise, you can use this:
http://simplehtmldom.sourceforge.net/
It's a sort of jQuery for PHP, meaning you can use HTML selectors to get portions of the code (i.e.: all the images, get the contents of a div, return only text (no HTML) contents of a node, etc).
You could do something like this (could be done more elegantly but this is just an example):
require_once("simple_html_dom.php");
function getContent ($item, $contentLength)
{
$raw;
$content = "";
$html;
$images = "";
if (isset ($item->content) && $item->content != "")
{
$raw = $item->content;
$html = str_get_html ($raw);
$content = str_replace("\n", "<BR /><BR />\n\n", trim($html->plaintext));
try
{
foreach($html->find('img') as $image) {
if ($image->width != "1")
{
// Don't include images smaller than 100px height
$include = false;
$height = $image->width;
if ($height != "" && $height >= 100)
{
$include = true;
}
/*else
{
list($width, $height, $type, $attr) = getimagesize($image->src);
if ($height != "" && $height >= 100)
$include = true;
}*/
if ($include == true)
{
$images = $images . '<div class="theImage"><img src="'.$image->src.'" alt="'.$image->alt.'" class="postImage" border="0" /></div>';
}
}
}
}
catch (Exception $e) {
// Do nothing
}
$images = '<div id="images">'.$images.'</div>';
}
else
{
$raw = $item->summary;
$content = str_get_html ($raw)->plaintext;
}
return (substr($content, 0 , $contentLength) . (strlen ($content) > $contentLength ? "..." : "") . $images);
}
file_get_contents() would work in this case assuming that you have allow_fopen_url set to true in your php.ini. What you would do is something like:
$pageContent = #file_get_contents($url);
if ($pageContent) {
preg_match_all('#<embed.*</embed>#', $pageContent, $matches);
$embedStrings = $matches[0];
}
That said, file_get_contents() won't give you much in the way of error handling other receiving the content on success or false on failure. If you would like to have more rich control over the request and access the HTTP response codes, use the curl functions and in particular, curl_get_info, to look at the response codes, mime types, encoding, etc. Once you get the content via either curl or file_get_contents() your code for parsing it to look for the HTML of interest will be the same.
Maybe Thumbshots or Snap already have some of the functionality you want?
I know that's not exactly what you are looking for, but at least for the embedded stuff that might be handy. Also txwikinger already answered your other question. But maybe that helps ypu anyway.

Problem with inserting an image in a form using GD!

I'm trying to develop a captcha class for my website everything was doing fine until I tried to embed the image generated with PHP GD inside my subscription form!
Here is the code of my class:
<?php
//captcha.php
header("Content-type: image/png");
class Captcha {
// some attributes bla bla
public function __construct($new_string_length,$new_width_picture,
$new_height_picture,$new_string_color) {
$this->string_length = $new_string_length;
$this->width_picture = $new_width_picture;
$this->height_picture = $new_height_picture;
$this->string_color = $new_string_color;
}
public function getString() {
return $this->string;
}
public function generateRandomString() {
$str = "";
$basket = "abcdefghijklmnopqrstuvwxyz0123456789";
$basket_length = strlen($basket);
srand ((double) microtime() * 1000000);
for($i=0;$i<$this->string_length;$i++) {
$generated_pos = rand(0,$basket_length);
$str_substr = substr($basket,$generated_pos-1,1);
if(!is_numeric($str_substr)) {
// if the character picked up isn't numeric
if(rand(0,1)==1) {
// we randomly upper the character
$str_substr = strtoupper($str_substr);
}
}
$str = $str.$str_substr;
}
$this->string = $str;
}
**public function generatePictureFromString($new_string) {
$root_fonts = '../fonts/';
srand ((double) microtime() * 1000000);
$list_fonts = array('ABODE.ttf','acme.ttf','Alcohole.ttf',
'Anarchistica.ttf','AMERIKAA.ttf');
$image = #imagecreatetruecolor($this->width_picture,$this->height_picture);
$noir = imagecolorallocate($image,0,0,0);
$clr = explode('/',$this->string_color);
$clr = imagecolorallocate($image,$clr[0],$clr[1],$clr[2]);
for($i=0;$i<strlen($new_string);$i++) {
imagettftext($image,rand(($this->height_picture/4.3),($this->height_picture)/4.2),
rand(-45,45),($this->width_picture)/(5*$this->string_length)+($this->width_picture)/($this->string_length)*$i,0.6*($this->height_picture),$clr,
$root_fonts.$list_fonts[rand(0,count($list_fonts)-1)],substr($new_string,$i,1));
}
imagepng($image);
imagedestroy($image);
}**
}
I willingly avoided to show some useless part of the class. The class itself works perfectly when I call the generatePictureFromString(..) method like this:
<?php
//testeur_classe.php
require_once '../classes/captcha.php';
$captcha = new Captcha(5,200,80,"255/255/255");
$captcha->generateRandomString();
$str = $captcha->getString();
$captcha->generatePictureFromString($str);
?>
But when I try to insert the picture generated in my form using:
<img src="<?php echo PATH_ROOT.'classes\testeur_classe.php'; ?>"/>
nothing is displayed!
How am I supposed to do that ?
Thank you!
OK: What do you see if you open classes\testeur_classe.php in the browser?
(p.s. the same question as Ryan Graham asked you in question comment)
OK: I think you must set correct headers before picture output like:
header('Content-type: image/png');
p.s.
This code works, just tried it on my machine. You must have bug on <img src="..." or <base href="" if you have one. Could you show us your html output so we can see what could be the problem?
You need to make sure that the image src is a valid URL to the script. Looking at the backslash in there my guess would be that that is in fact a filesystem path.

Categories