Link to home
Start Free TrialLog in
Avatar of sibas
sibas

asked on

more secure read and write! how can i do this?

Hello
in this program
i read one file

#include <iostream>
#include <fstream>
using namespace std;

int main(){
ifstream in ("Data/testtext.txt", ios::in);

if(!in) {
cout << "cannot open testtext.\n";
return 1;
}

char str[1000];
in.read(str, 999);
str[999] = '\0';
cout << ' ' << str;

in.close();
return 0;
}

in the file i have something like this

data2/somefolder/picture1
data2/somefolder/picture2

is it possible to put somewhere in the proggram
this
data2/somefolder/
so in the file i write only

picture1
picture2
...

my point here is to make more secure my proggram

thank you
Avatar of Jase-Coder
Jase-Coder

you could store the path in a constant or you could, you the windows API to get the current working directory

const char path[] = "data2/somefolder/picture1";

then you could do

strcat(path, filename);

I think this answer your question :S
Avatar of sibas

ASKER

Jase thanks, but is no way to working like this
first i am not working in windows
second i have more than 500 pictures to load
so to write 500 times
const char path[] = "data2/somefolder/picture1";
const char path[] = "data2/somefolder/picture2";
...
is a bit problem ;)
Are the files numbered 1..500?

i.e.
--------8<--------
#include <iostream>
#include <fstream>
#include <cstdio>
using namespace std;

int main()
{
      for (int i = 1;i <= 500;i++) {
            char filename[1024],str[1000];
            sprintf(filename,"data2/somefolder/picture%d",i);
            ifstream in(filename);
            if (!in) {
                  cerr << "Error: Unable to open " << filename << '\n';
                  continue;
            }
            in.read(str,999);
            str[999] = '\0';
            cout << str;
      }
}
--------8<--------
Avatar of sibas

ASKER

Thanks rstaveley
maybe i dont say in the right way what i want,
the pictures picture1, picture2, is only an example
is no way to know from begin the names of those pictures
maybe is sexygirl.png or nicemoon.gif
only the path i know
and because my proggram you can modify from internet
i have to make it more secure
thanks
Do you want it to process all files in a directory?

> and because my proggram you can modify from internet

You mean to say that your program can be edited and recompiled?? What are you guarding against?
Avatar of sibas

ASKER

i mean my program can read pictures from internet
when they stored in text file from internet,
but this is big risk if someone gives another path
i hope you realize what i mean
Ah I understand. You'll need to look for '/' to prevent people from getting clever with filenames like ../../../etc/passwd or whatever. You open a file with a bunch of filenames separated by newline characters.

--------8<--------
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(int argc,const char *argv[])
{
/* Open a file, which contains a list of filenames separated by newlines, specified at command line */
     if (argc < 2)
          return 1;
     ifstream filenames(*++argv);
     if (!filenames)
          return 1;
     string filename;
     while (getline(filenames,filename)) {
          if (filename.find('/') != string::npos)
               continue; // Path has a '/' - hacker reject!
          ifstream in(string("data2/somefolder/"+filename).c_str());
          if (!in) {
               cerr << "Error: Unable to open " << filename << '\n';
               continue;
          }
          // Your code from here....
          char str[1000];
          in.read(str,999);
          str[999] = '\0';
          cout << str;
     }
     return 0;
}
--------8<--------

Alternatively, for filenames separated by white space (i.e. no filenames with ' ' in them), use:
--------8<--------
     while (filenames >> filename) {
--------8<--------

This allows you to have more than one filename on the same line, which might be better for your CGI.
Avatar of sibas

ASKER

hi rstaveley
i try this, is really nice,
but somewhere i cant make it work
so i try like this
int main(int argc,const char *argv[])
{
ifstream in ("/home/tests/progr14a/data/Rrpictures", ios::in);
if(!in) {
cout << "cannot open Rrpictures.\n";
return 1;
}

     string filename;
     while (getline(in,filename)) {
          if (filename.find('/') != string::npos)
               continue; // Path has a '/' - hacker reject!
          ifstream in(string("data2/somefolder/"+filename).c_str());
          if (!in) {
              cerr << "Error: Unable to open " << filename << '\n';
               continue;
         }
          // Your code from here....
          char str[100];
         in.read(str,99);
          str[99] = '\0';
          cout << str;
     }
     return 0;
}

and i have this result

./readcpp
Error: Unable to open S10.jpg
Error: Unable to open s11.png

so this read the text but why it stop?

If it cannot read the files, it may be because your working directory isn't the directory you expected. Try using an absolute path (one that starts with '/').

e.g.

          ifstream in(string("/home/sibas/data2/somefolder/"+filename).c_str());

You will of course need to make the path right for your system :-)


Avatar of sibas

ASKER

i try olso this but i have the same results

if you try to open a text working for you?
Do you have permissions?
Avatar of sibas

ASKER

what you mean with this
i try with the same permissions that i have in my example,
for the text and dir
ASKER CERTIFIED SOLUTION
Avatar of rstaveley
rstaveley
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of sibas

ASKER

i am working with suse9
i try again but still i have problems
i will try latter and i let you know whats goin on
Avatar of sibas

ASKER

Hello  rstaveley
i accept your answer, but i cant make it work
i see the results like this
ÿØÿá
ÿØÿá

any idea about what is wrong
They are binary files, and and cout is going to stop printing as soon as it finds a '\0' character in the char buffer. My guess is that ÿØÿá corresponds to something in your image file header, which is followed by a 0x00 byte.

You need to use raw binary mode, if you are going to output binary data to standard output.

There are of course many ways to do this, but I quite like using streambuf_iterators.

e.g.
--------8<--------
#include <iostream>
#include <fstream>
#include <iterator>
#include <string>

using namespace std;

int main(int argc,const char *argv[])
{
/* Open a file, which contains a list of filenames separated by newlines, specified at command line */
     if (argc < 2)
          return 1;
     ifstream filenames(*++argv);
     if (!filenames)
          return 1;
     string filename;
     while (getline(filenames,filename)) {
          if (filename.find('/') != string::npos)
               continue; // Path has a '/' - hacker reject!
          ifstream in(string("data2/somefolder/"+filename).c_str());
          if (!in) {
               cerr << "Error: Unable to open " << filename << '\n';
               continue;
          }
          typedef istreambuf_iterator<char> Iitr; /* Input stream buffer iterator */
          typedef ostreambuf_iterator<char> Oitr; /* Output stream buffer iterator */
          Iitr iend; /* This gives us an object which we can use to test end of input */
          Oitr oitr(cout); /* Output stream buffer iterator for standard output */
          size_t count = 0; /* We are only going to handle the first 99 bytes */
          for (Iitr iitr(in);iitr != iend;++iitr) {
               *oitr = *iitr;
               if (++count == 99) /* Stop after 99 characters - if there are > 99 characters in the file */
                     break;
          }
     }
     return 0;
}
--------8<--------

If you find that this looks a bit freaky, you can use:

  // get length of file:
  in.seekg (0, ios::end);
  int length = in.tellg();
  in.seekg (0, ios::beg);
  char buf[99];
  in.read(buf,min(99,length));
  cout.write(buf,length);
Avatar of sibas

ASKER

this is weird
but like this working

cout << filename << '\n';
Was it the filename you wanted... not the contents of the file?
Avatar of sibas

ASKER

no the results is
B3.jpg
D10.jpg
D11.jpg

this is what i have in the text file
Avatar of sibas

ASKER

of course i am still have problem because is string end not char
> this is what i have in the text file

...but you wanted the contents of files B3.jpg, D10.jpg etc. Right?
Avatar of sibas

ASKER

i try to say it again (so sorry my english is not so good)

my program read text files and display pictures, text, music, etc

so in pictures.txt i have

data2/somefolder/B3.jpg
data2/somefolder/D10.jpg
...

with
char str[1000];
in.read(str, 999);
str[999] = '\0';
cout << str;

my proggram working just fine

now what i try to find is

how to write in text file only the
B3.jpg
D10.jpg
...
and the rest path somewhere inside the
ifstream in(string("/home/rob/src/"+thistext).c_str()

and when i do
cout << str;
to display all the path like
/home/rob/src/B3.jpg
/home/rob/src/D10.jpg
...

i dont know many thinks about c c++ i like it and i do it for hobby
thank you and sorry if i am trouble
I'm still having problems understanding your requirement.

From what can can gather, you start with input text file /home/tests/progr14a/data/Rrpictures, which contains a list of filenames with relative parths:

e.g.
  --------8<--------
  data2/somefolder/B3.jpg
  data2/somefolder/D10.jpg
  --------8<--------

You then want to create two output files.

(1) A list of files without their paths
e.g.
  --------8<--------
  B3.jpg
  D10.jpg
  --------8<--------

(2) A list of files with fully qualified paths
e.g.
  --------8<--------
  /home/tests/progr14a/data/B3.jpg
  /home/tests/progr14a/data/D10.jpg
  --------8<--------

If this is correct, let me know and I'll show you the code to do this. If I've misunderstood what you want, please could you describe what output files you want to create.
Avatar of sibas

ASKER

example

#include <iostream>
#include <fstream>
using namespace std;

int main(){
ifstream in ("Data/testtext.txt", ios::in);

HERE WE READ THE TEXT FILE, INSIDE
data2/somefolder/B3.jpg
data2/somefolder/D10.jpg
...

if(!in) {
cout << "cannot open testtext.\n";
return 1;
}

char str[1000];
in.read(str, 999);
str[999] = '\0';
cout << ' ' << str;

in.close();
return 0;
}

in the file i have something like this

data2/somefolder/picture1
data2/somefolder/picture2

is it possible to put somewhere in the proggram
this
data2/somefolder/
so in the file i write only

picture1
picture2
...
Avatar of sibas

ASKER

Yes i start with  /home/tests/progr14a/data/Rrpictures

inside the Rrpictures i have
  data2/somefolder/B3.jpg
  data2/somefolder/D10.jpg

with str i read this

  data2/somefolder/B3.jpg
  data2/somefolder/D10.jpg

and the proggram read the path and display the pictures

what i want is
in text file to write
B3.jpg
D10.jpg

and the rest path  /data2/somefolder/
to write somewhere inside the proggram

and when i do
cout << str;
then to display all the path
/data2/somefolder/B3.jpg
I still don't understand what you want your output files to be.

Do you want everything written to standard output (i.e. cout)?
Do you want anything written to an output file?
> and the rest path  /data2/somefolder/
> to write somewhere inside the proggram

That's the bit I can't understand. Do you mean you want to write this to a separate output file?
Avatar of sibas

ASKER

No i dont want it in seperate output file
i want something like

#include <iostream>
#include <fstream>
#include <string>

int main(int argc,const char *argv[])
{
    ifstream in (" /home/tests/progr14a/data/Rrpictures", ios::in);
        if(!in) {
                cout << "cannot open Rrpictures.\n";
                return 1;
        }

ifstream in(string("/data2/somefolder/"+TheNameOfPicture).c_str());

       
          char str[100];
          in.read(str,99);
          str[99] = '\0';
          cout << str;

//and the results of str must be /data2/somefolder/B3.jpg
...

     }
     return 0;
}

and the results of str must be /data2/somefolder/B3.jpg
...