I have a simple (excercise) website whose structure consist of a content selection menu and a content panel, where content is displayed when one the elements of the menu is selected.
The menu use links of the type ?content_id=... to pass the information over.
I would like to handle 404 codes on inexistent ids or missing contents but to do so I have to compute the content of the content panel befor the page loads, so that I can output the correct header before everything else. I ended up writing this piece of code at the beginning of my file and printing the $content variable when necessary. Anyway, I feel quiet uncomfortable with this approach since I have to stop the natural flow to catch the include output.
<?php
// if no content is specified in the address, select the home page (0)
$content_id = (isset($_GET['content_id'])) ? $_GET['content_id'] : 0;
//check if selected content exists and put the content inside the $content variable (to be used later)
if ($content_id < 0 OR $content_id > 2 OR !is_file('exContent/content'.$content_id.'.php')) {
header("HTTP/1.0 404 Not Found");
ob_start();
include 'exContent/noContent.php';
}
else {
ob_start();
include 'exContent/content'.$content_id.'.php';
}
$content = ob_get_contents(); ob_end_clean();
?>
I cannot figure out what's the best way to do this, I would be very happy if you can help me!
Could be a lot better but this is a start :)
$includeFile 'exContent/content'.$content_id.'.php';
if ($content_id < 0 OR $content_id > 2 OR !is_file( $includeFile )) {
header("HTTP/1.0 404 Not Found");
$includeFile = 'exContent/noContent.php';
}
ob_start()
include $includeFile;
$content = ob_get_contents();
ob_end_clean();
Related
I have a script that gets a streams link based on the external html page.
Is there a way to have one script and a resourced page with links to all the external links or do I need to have an individual page per request?
In other words, can I do this
example.com/videos.php?v=1234
or must I use
example.com/eachVideoPage.php
Here is the script I use to get the link.
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/xmpegURL");
?>
<?php
ob_start(); // ensures anything dumped out will be caught
$html = file_get_contents("http://example.com/aVideoPage.html");
preg_match_all(
'/(http:\/\/[^"].*?\.mp4)[",].*?/s',
$html,
$posts, // will contain the article data
PREG_SET_ORDER // formats data into an array of posts
);
foreach ($posts as $post) {
$link = $post[1];
// clear out the output buffer
while (ob_get_status())
{
ob_end_clean();
}
// no redirect
header("Location: $link");
}
?>
Assuming all you want to do is change the file_get_contents() URL It should be as simple as:
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/xmpegURL");
$vid = htmlspecialchars($_GET["v"]);
ob_start(); // ensures anything dumped out will be caught
$html = file_get_contents("http://example.com/$vid/aVideoPage.html");
preg_match_all(
'/(http:\/\/[^"].*?\.mp4)[",].*?/s',
$html,
$posts, // will contain the article data
PREG_SET_ORDER // formats data into an array of posts
);
foreach ($posts as $post) {
$link = $post[1];
// clear out the output buffer
while (ob_get_status())
{
ob_end_clean();
}
// no redirect
header("Location: $link");
}
?>
Updates:
$vid = htmlspecialchars($_GET["v"]);
Using _GET will take the URL Query parameters and do whatever you want with them. In this case a basic value assignment looking for ?v=123 in the URL. ($vid === '123')
It is worth mentioning that you should add some code to handle cases where ?v does not exists, or contains malicious input (depending on who uses it)
Then just reuse the value in the URL you want to call:
$html = file_get_contents("http://example.com/$vid/aVideoPage.html");
Update after comments
In order to call another site with a query string you can simply append it to the URL:
$html = file_get_contents("http://example.com/aVideoPage.html?v=$vid");
This will depend entirely on the remote site you are calling however. .html files usually won't do anything with query strings unless there is JavaScript in the code that uses it. But generally if you can browse to the remote URL with ?v=1234 in the URL and it selects the right video, then the above should also work.
I need to fetch a remote page, modify some elements (using 'PHP Simple HTML DOM Parser' library for that) and output modified content.
There's a problem with remote pages that don't have full URLs in their source, so CSS elements and images are not loaded. Sure, it doesn't stop me from modifying elements, but the output looks bad.
For example, open https://www.raspberrypi.org/downloads/
However, if you use code
$html = file_get_html('http://www.raspberrypi.org/downloads');
echo $html;
it will look bad. I tried to apply a simple hack, but that helps just a little:
$html = file_get_html('http://www.raspberrypi.org/downloads');
$html=str_ireplace("</head>", "<base href='http://www.raspberrypi.org'></head>", $html);
echo $html;
Is there any way to "instruct" script to parse all links from $html variable from 'http://www.raspberrypi.org'? In other words, how to make raspberrypi.org to be the "main" source of all images/CSS elements fetched?
I daon't know how to explain it better, but I believe you got an idea.
I just have tried this on local, and I've noticed(in the source code) the link tags in the HTML are like this:
<link rel='stylesheet' href='/wp-content/themes/mind-control/js/qtip/jquery.qtip.min.css' />
It obviously requires a file that should be in my local directory (like localhost/wp-content/etc.../).
The href of the link tags must be something like
<link rel='stylesheet' href='https://www.raspberrypi.org/wp-content/themes/mind-control/js/qtip/jquery.qtip.min.css' />
So what you probably want to do is find all link tags and add in their href attribute "https://www.raspberrypi.org/" in front of the rest.
EDIT: Hey I've actually made the style work, try this code:
$html = file_get_html('http://www.raspberrypi.org/downloads');
$i = 0;
foreach($html->find('link') as $element)
{
$html->find('link', $i)->href = 'http://www.raspberrypi.org'.$element->href;
$i++;
}
echo $html;die;
Since only Nikolay Ganovski offered a solution, I wrote a code which converts partial pages into full by looking for incomplete css/img/form tags and making them full. In case someone needs it, find the code below:
//finalizes remote page by completing incomplete css/img/form URLs (path/file.css becomes http://somedomain.com/path/file.css, etc.)
function finalize_remote_page($content, $root_url)
{
$root_url_without_scheme=preg_replace('/(?:https?:\/\/)?(?:www\.)?(.*)\/?$/i', '$1', $root_url); //ignore schemes, in case URL provided by user was http://domain.com while URL in source is https://domain.com (or vice-versa)
$content_object=str_get_html($content);
if (is_object($content_object))
{
foreach ($content_object->find('link.[rel=stylesheet]') as $entry) //find css
{
if (substr($entry->href, 0, 2)!="//" && stristr($entry->href, $root_url_without_scheme)===FALSE) //ignore "invalid" URLs like //domain.com
{
$entry->href=$root_url.$entry->href;
}
}
foreach ($content_object->find('img') as $entry) //find img
{
if (substr($entry->src, 0, 2)!="//" && stristr($entry->src, $root_url_without_scheme)===FALSE) //ignore "invalid" URLs like //domain.com
{
$entry->src=$root_url.$entry->src;
}
}
foreach ($content_object->find('form') as $entry) //find form
{
if (substr($entry->action, 0, 2)!="//" && stristr($entry->action, $root_url_without_scheme)===FALSE) //ignore "invalid" URLs like //domain.com
{
$entry->action=$root_url.$entry->action;
}
}
}
return $content_object;
}
I am trying to make "manner friendly" website. We use different declination dependent on gender and other factors. For example:
You did = robili
It did = robilo
She did = robila
Linguisticaly this is very simplified (and unlucky) example! I would like to change html text in php file where appropriate. For example
<? php
something
?>
html text of the page and somewhere is the word "robil"
<div>we tried to robil^i|o|a^</div>
<? php something ?>
Now I would like to replace all occurences of different tokens ^characters|characters|characters^ and replace them by one of their internal values according to "gender".
It is easy in javascript on the client side, but you will see all this weird "tokenizing" before javascript replace it.
Here I do not know the elegant solution.
Or do you have better idea?
Thanks for advice.
You can add these scripts before and after the HTML:
<?php
// start output buffering
ob_start();
?>
<html>
<body>
html text of the page and somewhere is the word "robil"
<div>we tried to robil^i|o|a^, but also vital^si|sa|ste^, borko^mal|mala|malo^ </div>
</body>
</html>
<?php
$use = 1; // indicate which declination to use (0,1 or 2)
// get buffered html
$html = ob_get_contents();
ob_end_clean();
// match anything between '^' than's not a control chr or '^', min 5 and max 20 chrs.
if (preg_match_all('/\^[^[:cntrl:]\^]{3,20}\^/',$html,$matches))
{
// replace all
foreach (array_unique($matches[0]) as $match)
{
$choices = explode('|',trim($match,'^'));
$html = str_replace($match,$choices[$use],$html);
}
}
echo $html;
This returns:
html text of the page and somewhere is the word "robil" we tried to
robilo, but also vitalsa, borkomala
I keep receiving this error when trying to add my own array into the code.
Here is my array;
$array = array();
while (odbc_fetch_row($rs))
{
$array[] = odbc_result($rs,'Product Name');
}
$test = print_r($array);
The original code is here. I'm using an example page to try it because I know the example page works fine.
http://www.tcpdf.org/examples/example_001.phps
This code is before the $html variable and when it is set I just add the $test variable into the $html variable. The odbc connection works fine and the example works fine before I add any code but when I run the script I get this error;
Array ( [0] => Test1 [1] => Test2 ) TCPDF ERROR: Some data has already been output, can't send PDF file
And there is also more than 2 items in the Array. Any ideas?
Add the function ob_end_clean(); before call the Output function.
It worked for me within a custom Wordpress function!
ob_end_clean();
$pdf->Output($pdf_name, 'I');
Just use ob_start(); at the top of the page.
Add the function ob_end_clean() before call the Output function.
I just want to add that I was getting this error, and nothing would fix it until I changed the Output destination parameter from F to FI.
In other words, I have to output to both file and inline.
Output('doc.pdf', 'I')
to
Output('doc.pdf', 'FI')
I have no idea why this made the difference, but it fixed the error for me...
This problem means you have headers. Deletes tags
?>
at the end of your code and make sure not to have whitespace at the beginning.
The tcpdf file that causes the "data has already been output" is in the tcpdf folder called tcpdf.php. You can modify it:
add the line ob_end_clean(); as below (3rd last line):
public function Output($name='doc.pdf', $dest='I') {
//LOTS OF CODE HERE....}
switch($dest) {
case 'I': {
// Send PDF to the standard output
if (ob_get_contents()) {
$this->Error('Some data has already been output, can\'t send PDF file');}
//some code here....}
case 'D': { // download PDF as file
if (ob_get_contents()) {
$this->Error('Some data has already been output, can\'t send PDF file');}
break;}
case 'F':
case 'FI':
case 'FD': {
// save PDF to a local file
//LOTS OF CODE HERE..... break;}
case 'E': {
// return PDF as base64 mime email attachment)
case 'S': {
// returns PDF as a string
return $this->getBuffer();
}
default: {
$this->Error('Incorrect output destination: '.$dest);
}
}
ob_end_clean(); //add this line here
return '';
}
Now lets look at your code.
I see you have $rs and $sql mixed up. These are 2 different things working together.
$conn=odbc_connect('northwind','****','*****');
if (!$conn) {
exit("Connection Failed: " . $conn);
}
$sql="SELECT * FROM products"; //is products your table name?
$rs=odbc_exec($conn,$sql);
if (!$rs) {
exit("Error in SQL");
}
while (odbc_fetch_row($rs)) {
$prodname=odbc_result($rs,"Product Name"); //but preferably never use spaces for table names.
$prodid=odbc_result($rs,"ProdID"); //prodID is assumed attribute
echo "$prodname";
echo "$prodid";
}
odbc_close($conn);
now you can use the $prodname and output it to the TCPDF output.
and I assume your are connecting to a MS access database.
Use ob_start(); at the beginning of your code.
for my case Footer method was having malformed html code (missing td) causing error on osx.
public function Footer() {
$this->SetY(-40);
$html = <<<EOD
<table>
<tr>
Test Data
</tr>
</table>
EOD;
$this->writeHTML($html);
}
I had this but unlike the OP I couldn't see any output before the TCPDF error message.
Turns out there was a UTF8 BOM (byte-order-mark) at the very start of my script, before the <?php tag so before I had any chance to call ob_start(). And there was also a UTF8 BOM before the TCPDF error message.
I had this weird error
and the culprit is a white space on the beginning of the PHP open tag
even without the ob_flush and ob_end_clean
Just make sure there are no extra white spaces on or after any <?php ?> block
use
ob_end_clean();
$pdf->Output($file, 'I');
to open pdf.
It works for me
I had the same error but finally I solved it by suppressing PHP errors
Just put this code error_reporting(0); at the top of your print page
<?php
error_reporting(0); //hide php errors
if( ! defined('BASEPATH')) exit('No direct script access allowed');
require_once dirname(__FILE__) . '/tohtml/tcpdf/tcpdf.php';
.... //continue
The error of "Some data has already been output, can't send PDF file" refers to the output buffer of PHP.
so you need to clean any content of the output buffer before sending output.
ob_end_clean(); // Clean any content of the output buffer
then
$pdf->Output('example_001.pdf', 'I'); // Send the PDF !
This problem is when apache/php show errors.
This data(html) destroy pdf output.
You must off display errors in php.ini.
For those who are still facing this issue try adding:
libxml_use_internal_errors(true);
before the loadHtml call and add
libxml_use_internal_errors(false);
after the call.
This solved it for me.
I'm trying to do some PDF generation in PHP. I found mPDF which generally has worked quite well. One problem I'm having though is that I need to be able to set separate headers for even/odd pages for some sections. I don't think the function is working right. Here's my code:
// load mPDF
// --------------------------------------------------------------------------
include('mpdf.php');
$mpdf = new mPDF();
// generate a lot of content so it spans multiple pages
// --------------------------------------------------------------------------
$i = 0;
$out = '';
while ($i < 300)
{
$i++;
$out .= '<p>Lorem Ipsum</p>';
}
// set html header for odd pages, write html and output
// --------------------------------------------------------------------------
$mpdf->SetHTMLHeader('ODD {PAGENO}', 'O');
$mpdf->WriteHTML($out);
$mpdf->Output();
When I run this code it puts "ODD Page 3" or whatever page it's on... on every page. Not just the odd pages. It seems to not consider naturally broken pages as new pages for the purposes of even or odd, only manually broken ones. If I run the AddPage() function it will consider the next group an even page. But that could be 50 auto page breaks later.
Any suggestions on how to get it to set different headers for actual even/odd pages, not just after manual page breaks?
your forget to write
$mpdf->mirrorMargins = 1;
here is your working example
<?php
include("../mpdf.php");
$mpdf=new mPDF('utf-8','A4');
$mpdf->debug = true;
$mpdf->mirrorMargins = 1 ;// Use different Odd/Even headers and footers and mirror margins
// generate a lot of content so it spans multiple pages
// --------------------------------------------------------------------------
$i = 0;
$out = '';
while ($i < 300)
{
$i++;
$out .= '<p>Lorem Ipsum</p>';
}
// set html header for odd pages, write html and output
// --------------------------------------------------------------------------
$mpdf->SetHTMLHeader('{PAGENO}/{nb}', 'O',true);
/* Note: SetHTMLHeader() and SetHTMLFooter() without a side(2nd argument)
- sets ODD page header/footer only as default..so you can also write just
$mpdf->SetHTMLHeader('{PAGENO}/{nb}'); */
$mpdf->WriteHTML($out);
$mpdf->Output();
exit;
?>
Reference:
setHTMLHeader