Uploading files on server using c++ wininet.h - php

I have written a code to upload text file on server using c++ wininet.h api..
The code runs fine but the file is not recieved on server side...
Can you guys please have a look why my code is not working.....
I have written a code on client side and on server side there is a php file in which i have checked $_FILES variable and written the code...
My client code
#include <windows.h>
#include <wininet.h>
#include <iostream>
#include<stdio.h>
#define ERROR_OPEN_FILE 10
#define ERROR_MEMORY 11
#define ERROR_SIZE 12
#define ERROR_INTERNET_OPEN 13
#define ERROR_INTERNET_CONN 14
#define ERROR_INTERNET_REQ 15
#define ERROR_INTERNET_SEND 16
using namespace std;
int main()
{
// Local variables
static char *filename = "C:\\test.txt"; //Filename to be loaded
static char *type = "image/jpg";
static char boundary[] = "pippo"; //Header boundary
static char nameForm[] = "uploadedfile"; //Input form name
static char iaddr[] = "localhost"; //IP address
static char url[] = "C:\\xampp\\htdocs\\test.php"; //URL
char hdrs[255]; //Headers
char * buffer; //Buffer containing file + headers
char * content; //Buffer containing file
FILE * pFile; //File pointer
long lSize; //File size
size_t result;
// Open file
pFile = fopen ( filename , "rb" );
if (pFile==NULL) return ERROR_OPEN_FILE;
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
content = (char*) malloc (sizeof(char)*lSize);
if (content == NULL) return ERROR_MEMORY;
// copy the file into the buffer:
result = fread (content,1,lSize,pFile);
if (result != lSize) return ERROR_SIZE;
// terminate
fclose (pFile);
//allocate memory to contain the whole file + HEADER
buffer = (char*) malloc (sizeof(char)*lSize + 2048);
//print header
sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",boundary,nameForm,filename);
sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type);
sprintf(buffer,"%s%s\r\n",buffer,content);
sprintf(buffer,"%s--%s--\r\n",buffer,boundary);
//Open internet connection
HINTERNET hSession = InternetOpen("WinSock",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hSession==NULL) return ERROR_INTERNET_OPEN;
HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
if(hConnect==NULL) return ERROR_INTERNET_CONN;
HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, (const char**)"*/*\0", 0, 1);
if(hRequest==NULL) return ERROR_INTERNET_REQ;
BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, strlen(buffer));
if(!sent) return ERROR_INTERNET_SEND;
//close any valid internet-handles
InternetCloseHandle(hSession);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
return 0;
}
My PHP code
<?php
$uploadfile = C:\xampp\htdocs\;
echo "<p>";
if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Upload failed";
}
echo "</p>";
echo '<pre>';
echo 'Here is some more debugging info: ';
print_r($_FILES);
print "</pre>";
?>
I am running this code on Code Blocks...
Actual: Code runs fine but the file is not recieved at server localhost...
EXPECTED: File to be recieved on server end localhost....
Please help this is my college project.
Reference = Upload file via POST

Related

Post image from linux (using c without curl) to php server

I am using v4l2 library on linux, take a picture and want to send it to a php server via c program.
I want to using a socket to do it. But i don't know how to pass the image to request .
This is my sample code:
int portno = 80;
struct sockaddr_in serv_addr;
int sockfd, bytes, sent, received, total;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
char message[1024],response[4096];
if (sockfd < 0){
printf("ERROR opening socket");
}
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
if(inet_pton(AF_INET, CONST_DOMAIN, &serv_addr.sin_addr)<=0){
printf("\n inet_pton error occured\n");
return 1;
}
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
printf("ERROR connecting");
}
char content[1024];
char *contentTemp="image_name=%s";
sprintf(content,contentTemp,imageName);
char *headerTemp="POST %supload.php HTTP/1.0\r\nHost: %s\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-length: %d\r\n\r\n%s";
sprintf(message,headerTemp,SERVICE_PATH,SERVICE_HOST,strlen(content),content);
write(sockfd,message,strlen(message));
Can i using this way to post an image to server (include its name) ?
Any suggest for me ?
Thanks
PS: sorry about my english skill.
You are including only file name. You have to include the whole image file contents into post data stream. Forms submitting binary data with POST request should use multipart/form-data content type. You can't use application/x-www-form-urlencoded type.
From HTML 4.01 specification:
The content type "application/x-www-form-urlencoded" is inefficient
for sending large quantities of binary data or text containing
non-ASCII characters. The content type "multipart/form-data" should be
used for submitting forms that contain files, non-ASCII data, and
binary data.
You could adjust your code like this:
char *filename="file.jpg"; // this example uses jpeg
// optionally load file from filesystem
// though I think you have it in a buffer, don't you?
FILE *file = fopen(filename, "rb");
char binary[1024]; // adjust buffer size to your needs
size_t filesize = fread(binary, 1, sizeof(binary), file);
// check for error here to make sure read succeeded
fclose(file);
// multipart/form-data POST header
const char *headerTemp = "POST %supload.php HTTP/1.0\r\n"
"Host: %s\r\n"
"Content-Type: multipart/form-data; boundary=BoUnDaRy\r\n"
"Content-Length: %lu\r\n"
"\r\n";
// first and only part beginning
const char *bodyTemp =
"--BoUnDaRy\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Transfer-Encoding: binary\r\n"
"\r\n";
// and ending
const char body2[] = "\r\n"
"--BoUnDaRy--\r\n";
char body1[1024]; // adjust buffer size to your needs
// calculate body size, will be included in Content-Length header
size_t body_size = strlen(body1) + strlen(body2) + filesize;
snprintf(header, 1024, headerTemp, SERVICE_PATH, SERVICE_HOST, body_size);
snprintf(body1, 1024, bodyTemp, filename);
// you should add checking for each write return value
write(sockfd, header, strlen(header));
write(sockfd, body1, strlen(body1));
write(sockfd, binary, filesize);
write(sockfd, body2, strlen(body2));
After sending data you should read server response, for example:
while (1) {
ssize_t result = recv(sockfd, response, sizeof(response), 0);
if (result == 0) {
break;
} else if (result < 0) {
perror("reading socket failed");
break;
}
printf("%s\n", response);
}
close(sockfd);
If you just close socket without waiting for the response server may complain and return error. You should also check if the response confirms valid request.

ZLIB inflate give 'data error' in PHP

I've got a file that has zlib deflated blocks of 4096 bytes. I'm able to inflate at least 1 block of 4096 bytes with C++, using Minzip's inflate implementation, without garbled text or data error.
I'm using the following C++ implementation to inflate the data:
#define DEC_BUFFER_LEN 20000
int main(int argc, char* argv[]) {
FILE *file = fopen("unpackme.3di", "rb");
char *buffer = new char[4096];
std::fstream outputFile;
outputFile.open("output.txt", std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
// Data zit nu in de buffer
char *decbuffer = new char[DEC_BUFFER_LEN];
mz_streamp streampie = new mz_stream();
streampie->zalloc = Z_NULL;
streampie->zfree = Z_NULL;
streampie->opaque = Z_NULL;
streampie->avail_in = Z_NULL;
streampie->next_in = Z_NULL;
if (inflateInit(streampie) != Z_OK)
return -1;
fread(buffer, 1, 4096, file);
streampie->next_in = (Byte *)&buffer[0];
streampie->avail_in = 4096;
streampie->next_out = (Byte *)&decbuffer[0];
streampie->avail_out = DEC_BUFFER_LEN;
streampie->total_out = 0;
int res = inflate(streampie, Z_NO_FLUSH);
if (res != Z_OK && res != Z_STREAM_END) {
std::cout << "Error: " << streampie->msg << std::endl;
return;
}
outputFile.write(decbuffer, streampie->total_out); // Write data to file
fclose(file);
inflateEnd(streampie);
outputFile.flush();
outputFile.close();
getchar();
return 0;
}
and I'm using the following PHP implementation:
function Unpack3DI($inputFilename) {
$handle = fopen($inputFilename, 'rb');
if ($handle === false) return null;
$data = gzinflate(fread($handle, 4096));
return $data;
}
var_dump(Unpack3DI('unpackme.3di'));
Result:
Warning: gzinflate() [function.gzinflate]: data error in /var/www/html/3di.php on line 9
bool(false)
The issue was that I used the wrong function. I had to use gzuncompress instead of gzinflate.
Also, pushing the whole file in gzuncompress did the job very well actually, as zlib checks if there are remaining blocks to be uncompressed.
More information about the Zlib methods in PHP are answered in this answer to "Which compression method to use in PHP?".

Sending binary commands from PHP to Arduino powered thermal printer

I am having some fun playing around with an Arduino (Uno rev 3) and a thermal printer (this model https://www.sparkfun.com/products/10438). The Arduino makes a request every 10 seconds to my local machine (via an Ethernet shield) and stores the response (if 200) on an SD card. It then prints this out using this library https://github.com/adafruit/Adafruit-Thermal-Printer-Library .
So far I have it correctly polling, storing and printing basic text but now I'm trying to use some of the more advanced commands (underline, inverse etc). My ultimate goal is to send images down and handle all of the rendering on the server ala http://printer.gofreerange.com/ .
The problem is that the commands I am sending are been outputted as text characters. Some commands work (line feed), but others are garbled. I have attached both the Arduino code and the basic PHP script it is calling. Any help?
Arduino:
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include "Adafruit_Thermal.h"
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
const char host[] = "192.168.1.100";
char cacheFilename[] = "TMP";
const byte printer_RX_Pin = 8; // this is the green wire
const byte printer_TX_Pin = 9; // this is the yellow wire
const byte SD_Pin = 4; // the SD Card SPI pin
bool downloadWaiting = false;
bool statusOk = false;
unsigned long content_length = 0;
EthernetClient client;
Adafruit_Thermal printer(printer_RX_Pin, printer_TX_Pin);
void die(unsigned int times) {
while(true);
}
void checkForDownload() {
Serial.println("checkForDownload");
content_length = 0;
statusOk = false;
unsigned long length = 0;
if (SD.exists(cacheFilename)) {
if (!SD.remove(cacheFilename)) {
die(4);
}
}
File cache = SD.open(cacheFilename, FILE_WRITE);
if(client.connect(host, 80)) {
client.println("GET /printer.php HTTP/1.1");
client.print("Host: "); client.println(host);
client.println("User-Agent: arduino-ethernet");
client.println("Connection: close");
client.println();
bool parsingHeader = true;
while(client.connected()) {
while(client.available()) {
if (parsingHeader) {
client.find((char*)"HTTP/1.1 ");
char statusCode[] = "000";
client.readBytes(statusCode, 3);
statusOk = (strcmp(statusCode, "200") == 0);
client.find((char*)"Content-Length: ");
char c;
while (isdigit(c = client.read())) {
content_length = (content_length * 10) + (c - '0');
}
client.find((char*)"\n\r\n");
parsingHeader = false;
} else {
if(length < content_length) {
cache.write((byte)client.read());
length++;
} else {
client.read();
}
}
}
}
client.stop();
cache.seek(0);
if (statusOk && content_length > 0 && (content_length == length) && (content_length == cache.size())) {
downloadWaiting = true;
}
} else {
client.stop();
}
cache.close();
}
void printFromDownload() {
Serial.println("printFromDownload");
File cache = SD.open(cacheFilename);
byte b;
while (content_length--) {
printer.write((byte)cache.read());
}
printer.feed();
cache.close();
downloadWaiting = false;
}
void setup(){
pinMode(SD_Pin, OUTPUT);
if (!SD.begin(SD_Pin)) {
die(2);
}
if (Ethernet.begin(mac) == 0) {
die(3);
}
Serial.begin(9600);
printer.begin(255);
delay(1000);
}
void loop() {
if (downloadWaiting) {
printFromDownload();
delay(5000);
} else {
checkForDownload();
if (!downloadWaiting) {
delay(10000);
}
}
}
PHP:
<?php
ob_start();
// Turn on Inverse mode
// Doesn't work
echo pack('S', 29);
echo pack('S', 66);
echo pack('S', 1);
$string = 'Testing 1, 2, 3';
foreach(str_split($string) as $char) {
echo pack('S', ord($char)); // works
}
// Turn off Inverse mode
echo pack('S', 29);
echo pack('S', 66);
echo pack('S', 0);
// Line feed
echo pack('S', 10); // works
$content = ob_get_clean();
$length = strlen($content);
header("Content-Length: $length");
echo $content;
It seems that you can't print bitmap data directly with printer.write(). The printer expects some special bytes to turn on bitmap printing mode as you can see in the printBitmap() method. (writeBytes(18, 42, chunkHeight, rowBytesClipped))
void Adafruit_Thermal::printBitmap(
int w, int h, const uint8_t *bitmap, bool fromProgMem) {
int rowBytes, rowBytesClipped, rowStart, chunkHeight, x, y, i;
rowBytes = (w + 7) / 8; // Round up to next byte boundary
rowBytesClipped = (rowBytes >= 48) ? 48 : rowBytes; // 384 pixels max width
for(i=rowStart=0; rowStart < h; rowStart += 255) {
// Issue up to 255 rows at a time:
chunkHeight = h - rowStart;
if(chunkHeight > 255) chunkHeight = 255;
writeBytes(18, 42, chunkHeight, rowBytesClipped);
for(y=0; y < chunkHeight; y++) {
for(x=0; x < rowBytesClipped; x++, i++) {
PRINTER_PRINT(fromProgMem ? pgm_read_byte(bitmap + i) : *(bitmap+i));
}
i += rowBytes - rowBytesClipped;
}
timeoutSet(chunkHeight * dotPrintTime);
}
prevByte = '\n';
}
Your sketch will need to understand the data coming from the PHP and know when to send individual characters as bytes with printer.write() and when to send bytes as an image with printer.printBitmap(). This way the printer is receiving the proper commands to prep it for printing the appropriate data. You will need to construct some metadata around what you want to print in PHP and send that to the Arduino. A JSON format might look like this:
{"reciept": [
{
"type": "text",
"style": "bold",
"value": "Thank you for your purchase"
},
{
"type": "bitmap",
"pos": "center",
"value": ".... binary data ..."
}
]}
Now your Arduino sketch will understand when to send bytes individually as text and when to send a lot of data as a bitmap.
A more compact format might use line feeds as a break between segments:
F|bold
T|Thank you for shopping with us\r
P|Center
B|...binary data (with \r escaped)... \r
Or, you can send the amount of data with each segment to avoid escaping binary data much like the Content-Length header of HTTP
F4|boldT32|Thank you for shopping with us\rP6|CenterB3000|...binary data...

How to read PHP's -gzcompress- data from c++

This is my c++ code:
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QFile>
#include <QByteArray>
QByteArray UnZip (QString zipfilename)
{
QFile infile(zipfilename);
infile.open(QIODevice::ReadOnly);
//QByteArray uncompressedData = infile.readAll();
QByteArray uncompressedData = qUncompress(infile.readAll());
infile.close();
return uncompressedData;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//QString path = "/Users/davide/Desktop/fh8RkbUf";
QString path = "/Users/davide/Desktop/test";
QByteArray data = UnZip(path);
qDebug() << "message";
return a.exec();
}
; that returns qUncompress: Z_DATA_ERROR: Input data is corrupted
However, data should be zlib compressed and php's gzuncompress($data) works fine.
Also, cat file | uncompress returns errors.
The code php side is
$data = gzcompress($data, 6);
$success = file_put_contents($file, $data);

How can I handle packed data from Perl/PHP in C++?

I got a problem implementing a PHP programm in C++. It is about the PHP/Perl function unpack. I don't know how to do the follwing in C++ (no problem in reading a file... but how do i unpack("C*") the read contents).
<?php
$file = fopen("bitmaskt.dat", "rb");
//create the data stream
$matrix_x = unpack("C*", fread($file, 286));
$matrix_y = unpack("C*", fread($file, 286));
$mask_data = unpack("C*", fread($file, 286));
$reed_ecc_codewords = ord(fread($file, 1));
$reed_blockorder = unpack("C*", fread($file, 128));
fclose($file);
?>
Currently, I'm very hopeless solving this problem on my own - I'm searching for days, all I found are questions... Is there any free unpack() c++ implementation out there? :-(
Perl's documentation for pack covers the templates used for pack and unpack.
Say you generated bitmaskt.dat with
#! /usr/bin/perl
use warnings;
use strict;
open my $fh, ">", "bitmaskt.dat" or die "$0: open: $!";
my #data = (42) x 286;
print $fh pack("C*" => #data);
print $fh pack("C*" => #data);
print $fh pack("C*" => #data);
print $fh pack("C" => 7);
print $fh pack("C*" => (1) x 128);
close $fh or warn "$0: close";
You might read it with
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
typedef unsigned char datum_t;
typedef std::vector<datum_t> buf_t;
std::istream &read_data(std::istream &in, buf_t &buf, size_t n)
{
std::istreambuf_iterator<char> it(in.rdbuf()), eos;
while (it != eos && n-- != 0)
buf.push_back(static_cast<datum_t>(*it++));
return in;
}
For example:
int main()
{
std::ifstream bm("bitmaskt.dat", std::ifstream::binary | std::ifstream::in);
struct {
buf_t buf;
size_t len;
std::string name;
} sections[] = {
{ buf_t(), 286, "matrix_x" },
{ buf_t(), 286, "matrix_y" },
{ buf_t(), 286, "mask_data" },
{ buf_t(), 1, "reed_ecc_codewords" },
{ buf_t(), 128, "reed_blockorder" },
};
const int n = sizeof(sections) / sizeof(sections[0]);
for (int i = 0; n - i > 0; i++) {
if (!read_data(bm, sections[i].buf, sections[i].len)) {
std::cerr << "Read " << sections[i].name << " failed" << std::endl;
return 1;
}
}
const int codeword = 3;
std::cout << (unsigned int) sections[codeword].buf[0] << '\n';
return 0;
}
Output:
7
I don't know about any general implementation of unpack for C++, but that doesn't seem to be the thing you need anyway.
if matrix_x is defined somewhere as unsigned char matrix_x[286] and you have an opened input stream inFile
then what you need to do is inFile.get(matrix_x, 286). This reads 286 bytes from the input and places them in the array pointed to by matrix_x.

Categories