#1 2010-07-13 22:59

auwebio
Member
From: Brazil
Registered: 2010-07-07
Posts: 45

A Timestamp problem: take from name and set on file

Hello, Denis.
I'm a long time user of ReNamer (since around 2006).

Before it, I used another small tool to queue the files, copy their names to clipboard, edit them using regex at NoteTab Pro and paste back to the app to rename them. You have been saving me a LOT of time and allowing me to do the most sophisticated renaming operations ever (besides the great possibilities of presets, etc, etc). For that I am the most thankful to you!  smile

I've seen you partially address my problem on another topic (below), but since mine is actually much simpler and a different problem, I thought I could address it here:

Besides renaming the files (which ReNamer already does wonderfully!), I have a need to alter the "modified" timestamp of quite a lot of files.

There are a million applications to do it 1-file-at-a-time and very few (like AttributeMagic) that would allow you to do it all at once. I can testify that I've been searching for years for an application that would do well what I need and I haven't found one yet. I have my hopes high on you and I really think ReNamer might do it.

So, my problem is:
- It's easy for me to compile a table with the filenames (including path) and the "modified" time it needs to be reverted back to, but AttributeMagic won't take any input method for those files (like clipboard, .txt or .csv file), other than the filenames themselves.
- So, I need to enqueue all the files in ReNamer, then prefix all the files with the dates I need, using the "user input", then enqueue all the exact same files (now with new names - more complicated) in AttributeMagic, use the date prefix to modify the timestamp, then go back to ReNamer and revert the filename modification. (I'm not complaining! Thank God we've got ReNamer!)

Finally, here's my line of thought:
• You have an application that already allows us to enqueue a lot of files;
• The same application have already a method that allows it to read an user input either from clipboard or text files;
• I see that you already have a function to read the "modified" timestamp of those very files (:File_DateModified:);
--> so, I wonder that perhaps it wouldn't be so hard to have a new function that, instead of reading, writes timestamps to the files, based on the user input.

I understand that you do not want to loose the renaming focus of the application (as stated below), and I completely respect that, but let me just consider this:

1 - If the timestamp writing function is simple and small enough, why not add it as an "extra" to the application, even "hidden" in the file menu, as to avoid cluttering the very clean interface of ReNamer. I don't believe doing like that would detract from the focus of ReNamer - it would be more like giving the user a bonus functionality, taking advantage of the already spectacular, flexible and well-rounded interface of the program that already exists.

2 - In the event that you don't agree with my statement above, maybe you could consider writing a "sister application", using almost the same interface as ReNamer, but only focused on timestamp modifying. You could start with just the simple user input option on the first version and then go on to add other options and improve it as time allows it.

3 - If you're not interested in either options 1 or 2, would you then consider sharing some source code with me, so that I can try to write that application described above myself. I'm not looking to distribute or take credit for it in any way, shape or form. I just need to use it and I would be willing to write the program under your suppervision/approval and give you all the code and credits for it. Without the "head-start" for the file-handling and interface capabilities, I'm afraid I wouldn't be able to write this program, so that's why I am shamelessly (as a last resource) asking you this.

I'm sorry for such a long request; I wanted to explain and make myself as clear as possible.  smile

Again, my most sincere thank you for the use of ReNamer and congratulations on such a wonderful application.  wink

shonu wrote:

Renamer: Writing from EXIF-Timespamp to File-Timestamp and vice-versa
It would be helpful to be able to: a) extract the date from filename ->EXIF / b) extract the date from filename ->timestamp of the file

den4b wrote:

...these are good ideas! But unfortunately they are not really about renaming files... There are many tools...that can do all that...I'm afraid I can't see a good place for these features in ReNamer...


PS: I even tried once to write an application myself for doing the job and I wasn't very successful. I wrote a very good and complete requirements paper, but when I got to Delphi to implement it, things didn't work quite so well...

Offline

#2 2010-07-14 03:31

SafetyCar
Senior Member
Registered: 2008-04-28
Posts: 446
Website

Re: A Timestamp problem: take from name and set on file

Hi,

I've donde a code to help you.

You can keep using the same way of input you were doing before (UserInput), the date formate needs to be "yyyy-mm-dd hh.nn.ss" (example: 2010-07-14 03.25.00).

If it's better for you with other date format... Just say it.


To use de code you'll have to paste it in a PascalScript Rule.

Please take care, the date change happens when you hit Preview, NOT on rename.

I recommend you to do some tests with useless files (or copies)

var
  DateMod: TDateTime;
  DatePart: TStringsArray;
  Year, Month, Day: Word;

begin
  If length(MatchesRegEx(FileName, '(\d{4})-(\d{1,2})-(\d{1,2}) (\d{1,2}).(\d{1,2}).(\d{1,2})', False))>0 then
  begin
    DatePart := SubmatchesRegEx(FileName, '(\d{4})-(\d{1,2})-(\d{1,2}) (\d{1,2}).(\d{1,2}).(\d{1,2})', False);
  
    Year  := StrToInt(DatePart[0]);
    Month := StrToInt(DatePart[1]);
    Day   := StrToInt(DatePart[2]);
  
    DateMod := EncodeDate(Year, Month, Day);
    DateMod := IncHour(DateMod, StrToInt(DatePart[3]));
    DateMod := IncMinute(DateMod, StrToInt(DatePart[4]));
    DateMod := IncSecond(DateMod, StrToInt(DatePart[5]));
  
    If SetFileTimeModified(FilePath, DateMod) then
      FileName := ':: OK >> Date changed succesfully ::'
    else
      FileName := ':: FAIL >> Date not changed ::';
  end
  else
  begin
    FileName := ':: FAIL >> No date found ::';
  end;
end.

Info taken from: http://www.den4b.com/wiki/ReNamer:Pasca … #File_Time

Last edited by SafetyCar (2010-07-14 03:44)


If this software has helped you, consider getting your pro version. :)

Offline

#3 2010-07-14 07:55

Stefan
Moderator
From: Germany, EU
Registered: 2007-10-23
Posts: 1,161

Re: A Timestamp problem: take from name and set on file

Hi auwebio, welcome.

To "alter the "modified" timestamp" of files, i would use
an file manager like Total Commander with an Plugin or XYplorer with scripting.

Or
NirSoft FileDate Changer > http://www.nirsoft.net/utils/filedatech.html
or
NewFileTime 1.24 > http://www.softwareok.com/?seite=Microsoft/NewFileTime


Read the  *WIKI* for HELP + MANUAL + Tips&Tricks.
If ReNamer had helped you, please *DONATE* to Denis or buy a PRO license. (Read *Lite vs Pro*)

Offline

#4 2010-07-14 17:29

Andrew
Senior Member
Registered: 2008-05-22
Posts: 542

Re: A Timestamp problem: take from name and set on file

auwebio wrote:

- It's easy for me to compile a table with the filenames (including path) and the "modified" time it needs to be reverted back to, but AttributeMagic won't take any input method for those files (like clipboard, .txt or .csv file), other than the filenames themselves.

The main job is compiling that table. If you can do that, your job's almost done. AtributeMagic might not accept any input methods, but if you have a command line utility that takes the filename and creation/modification/access date/time as parameters (Google gives me plenty), it's relatively easy to create a batch file with each line changing the date/time of a single file. Run the batch file and voila! big_smile

Last edited by Andrew (2010-07-14 17:31)

Offline

#5 2010-07-14 17:33

auwebio
Member
From: Brazil
Registered: 2010-07-07
Posts: 45

Re: A Timestamp problem: take from name and set on file

SafetyCar wrote:

...same way of input...date formate needs to be "yyyy-mm-dd hh.nn.ss"...If it's better for you with other date format... Just say it.

Hello, SafetyCar!
First of all, my most sincere thanks for even taking interest in my problem! As for the date format, it's very easy for me to have the output adjusted to whatever format I need. This one you gave me is very usual and perfectly fine.

SafetyCar wrote:

...PascalScript Rule...date change happens when you hit Preview...do some tests with useless files

I had considered writing the Script myself before, but then I had so many doubts that I thought it would be better to wait for an opportunity where I could fully read about the functions that were available in PascalScript, all the input methods and user dialogs, and figure out if the files were processed one-by-one in the script (which would mean I couldn't have a "confirm" dialog inside the script) or all-at-once (then I could have a "confirm" dialog), etc, etc...

Your script already saves me a lot of time. Thank you! It sure works, but... The only problem is that I have to be extra-extra-careful with the input, making sure I always paste the exact number of dates and, most importantly, in the exact correspondence order of the files. Writing some automated check for the date input before I copy is easy; and I can always generate a file list with path and names (instead of dragging them to ReNamer); But, since there is no preview of the output before applying the script, the matching part between the files and the dates remain entirely dependent on me not "messing up" either in the order of the dates input or the number of them, etc. Still, I do believe this is a better system than the one I've been using currently and I really thank you for that.

SafetyCar wrote:

If length(MatchesRegEx(FileName, '(\d{4})-(\d{1,2})-(\d{1,2}) (\d{1,2}).(\d{1,2}).(\d{1,2})', False))>0
// Checking the if the input matches the exact format for date.

I'm assuming the user input then must be set to "Replace the current name" and "Skip extension" is unmarked then.
Since the objective is not really about changing the name this is completely fine  wink (setting the filename to be the full date with seconds as extension).
When I hit preview, I could actually see the new dates beside the original files, thus giving me a "sort of"  wink visual confirmation. I just must never (ever!) hit the Rename button.  lol

SafetyCar wrote:

If SetFileTimeModified(FilePath, DateMod) then
  FileName := FileName + ' - OK -- Date changed succesfully'
else FileName := FileName + ' - FAIL -- Date not changed';

I did a tiny modification in the script so that I could still see the corresponding "new date" input after the preview, I hope you don't mind. (I also took out the :: and the >> from the final messages, as to avoid the "warning! found n invalid filename(s)!" message, which will now only appear if there's either no input for a file or exact same date for more than one file)

Thanks for pointing me to this page of information! It is really useful.

So, here's the final code for the "TimeStamper" (thanks to SafetyCar), if anyone else want to take advantage of it:

[Rule0]
ID=UserInput
Config=INPUT:;ACTION:0;SKIPEXTENSION:0
Marked=1

[Rule1]
ID=PascalScript
Config=SOURCE:var%0D%0A++DateMod%3A+TDateTime%3B%0D%0A++DatePart%3A+TStringsArray%3B%0D%0A++Year%2C+Month%2C+Day%3A+Word%3B%0D%0A%0D%0Abegin%0D%0A++If+length%28MatchesRegEx%28FileName%2C+%27%28%5Cd%7B4%7D%29%2D%28%5Cd%7B1%2C2%7D%29%2D%28%5Cd%7B1%2C2%7D%29+%28%5Cd%7B1%2C2%7D%29%2E%28%5Cd%7B1%2C2%7D%29%2E%28%5Cd%7B1%2C2%7D%29%27%2C+False%29%29%3E0+then%0D%0A++begin%0D%0A++++DatePart+%3A%3D+SubmatchesRegEx%28FileName%2C+%27%28%5Cd%7B4%7D%29%2D%28%5Cd%7B1%2C2%7D%29%2D%28%5Cd%7B1%2C2%7D%29+%28%5Cd%7B1%2C2%7D%29%2E%28%5Cd%7B1%2C2%7D%29%2E%28%5Cd%7B1%2C2%7D%29%27%2C+False%29%3B%0D%0A++%0D%0A++++Year++%3A%3D+StrToInt%28DatePart%5B0%5D%29%3B%0D%0A++++Month+%3A%3D+StrToInt%28DatePart%5B1%5D%29%3B%0D%0A++++Day+++%3A%3D+StrToInt%28DatePart%5B2%5D%29%3B%0D%0A++%0D%0A++++DateMod+%3A%3D+EncodeDate%28Year%2C+Month%2C+Day%29%3B%0D%0A++++DateMod+%3A%3D+IncHour%28DateMod%2C+StrToInt%28DatePart%5B3%5D%29%29%3B%0D%0A++++DateMod+%3A%3D+IncMinute%28DateMod%2C+StrToInt%28DatePart%5B4%5D%29%29%3B%0D%0A++++DateMod+%3A%3D+IncSecond%28DateMod%2C+StrToInt%28DatePart%5B5%5D%29%29%3B%0D%0A++%0D%0A++++If+SetFileTimeModified%28FilePath%2C+DateMod%29+then%0D%0A++++++FileName+%3A%3D+FileName+%2B+%27+%2D+OK+%2D%2D+Date+changed+succesfully%27%0D%0A++++else%0D%0A++++++FileName+%3A%3D+FileName+%2B+%27+%2D+FAIL+%2D%2D+Date+not+changed%27%3B%0D%0A++end%0D%0A++else%0D%0A++begin%0D%0A++++FileName+%3A%3D+%27+%3A%3A+FAIL+%3E%3E+No+date+found%27%3B%0D%0A++end%3B%0D%0Aend%2E
Marked=1

Offline

#6 2010-07-14 17:50

auwebio
Member
From: Brazil
Registered: 2010-07-07
Posts: 45

Re: A Timestamp problem: take from name and set on file

Stefan wrote:

To "alter the "modified" timestamp" of files, i would use
an file manager like Total Commander with an Plugin

Hello, Stefan!  Thank you very much for your reply! smile
I've been using Ghisler Commander for more than 10 years now, I believe. Which plugin are you refering to? (I might even have it here left unused... or I might consider getting it)

Stefan wrote:

..or XYplorer with scripting. Or
NirSoft FileDate Changer > http://www.nirsoft.net/utils/filedatech.html or
NewFileTime 1.24 > http://www.softwareok.com/?seite=Microsoft/NewFileTime

Unfortunately NirSoft doesn't work for me, it seams to change a lot of files but all to a single date at a time.
Same thing for NewFileTime: many files, but single date at once. This seams to be the case for most of these utilities I've encountered for many years now. I just wish someone would break this paradigm...

Anyway, thank you very much for trying to help me. I appreciate it.  smile

Offline

#7 2010-07-14 18:46

auwebio
Member
From: Brazil
Registered: 2010-07-07
Posts: 45

Re: A Timestamp problem: take from name and set on file

Andrew wrote:

The main job is compiling that table. If you can do that, your job's almost done. AtributeMagic might not accept any input methods, but if you have a command line utility that takes the filename and creation/modification/access date/time as parameters (Google gives me plenty), it's relatively easy to create a batch file with each line changing the date/time of a single file. Run the batch file and voila! big_smile

Hello, Andrew! Wow...  yikes
I can't believe that thought never even crossed my mind yet... It's so simple! Thank you very much! (I might even use pure DOS functions, without the need for the command line utility - I have to research more on that, though...)
The only problem with that method is that I do not get any sort of warning or confirmation of any kind; if I "mess up" any information in the way I might not even notice afterwards.

Thank you for your help!  wink

Offline

#8 2010-07-14 19:32

auwebio
Member
From: Brazil
Registered: 2010-07-07
Posts: 45

Re: A Timestamp problem: take from name and set on file

A small doubt that has arisen after  SafetyCar's Script:

I was wondering if there shouldn't be a menu option to load file lists?

e.g.: File > Add List of Files

or a more "elegant" way, other than the command prompt or an improvised shortcut. I tried to search the forum, but couldn't find anything so far... (except Stefan's Total Commander shortcut, but that doesn't really help me specifically in this case). Please, don't get me wrong; I love that we even have this option, but I'm kind of wishing it could be a tiny bit easier to use.  big_smile

Offline

#9 2010-07-14 19:33

Stefan
Moderator
From: Germany, EU
Registered: 2007-10-23
Posts: 1,161

Re: A Timestamp problem: take from name and set on file

I had Romans AddTime (http://www.angelfire.com/sk/thehacker/a … index.html)
or ReDate (http://www.angelfire.com/sk/thehacker/redate/index.html)
in mind.
But this works like NirSofts tool and use one single rule for all selected files.

So can you once more explain what you wanna do?
You have
- some files
- an list with this path\names and the mod date for each file
X:\Path\file.ext, 12.03.1997 12:34
X:\Path\other.ext, 3.12.1999 23:45

You want to modify the mod date of each file like listed.
For Each File in Files
  IF Name = X:\Path\file.ext Then
      Mod date = 12.03.1997 12:34
  End IF
Next

Is this right?

Question:
How many files?
With sub-folders?
Are there different paths? Or one main path to start with?

Your list is in sync with the files? I mean your list is sorted as the files and there are no file left or to much?
Can you execute this script-to-come for every single folder, or have the script to detect the folder change too?



I have in mind:

Folder_1
For first file "File A.ext"
--- Read first line from List.txt: "File A.ext, 14.07.2010 21.03"
----- IF (Split(line,",")[0]==FileName) THEN 
---------- vSTAMP = Split(line,",")[1] //14.07.2010 21.03
---------- vSTAMP = replace(vSTAMP, space&dots) //140720102103
------------ execute touch -t vSTAMP --time=mtime FileName
For next file "File B.ext"
--- Read next line from List.txt: "File B.ext, 10.03.2010 09.45"
----- IF


.

Something like this demo script.
I just have to use an more comfortable DOS executable
and make this all recursive.

var
        I: Integer;
        Item, Name, Time: WideString;
        dummy: String;
        Parts: TStringsArray;

begin
        I := I + 1;
        Item := FileReadLine('C:\Temp\Names.txt', I);
        Parts := WideSplitString(Item, ',');
        Name := Parts[0];
        Time := Parts[1];

        IF (FileName=Name) Then
        begin
            Time := WideReplaceStr(Time,' ','');
            Time := WideReplaceStr(Time,'.','');
            Time := WideReplaceStr(Time,':','');
            
                //-t STAMP  use MMDDhhmm[[CC]YY][.ss] instead of current time
                ShowMessage('touch -t ' +Time+ ' --time=mtime ' + FilePath);
                ExecConsoleApp('touch -t ' +Time+ ' --time=mtime ' + FilePath, dummy);
                
                //setfiletime [filename or wildcard] [Created Date] {Modified Date} {Accessed Date} 
                //ExecConsoleApp( 'NirSoft setfiletime '+FilePath+' "" "24-06-2003 17:57:11" "" ', dummy);
        end;
end.


-----------------------------------------------------------

EDIT:
I think my solution was not what was wanted, but since i started i will post here my code just for the record:

Change the modify date of files according to an list.

1.) I have an list of file names - coma - timestamp:
C:\Temp\Names.txt
1.html, 02.03.1981 10:10
2.html, 17.09.2009 23:23

2.) i need an external tool to change the modify date of an file.
I have found several tools, but there is none i like much till now, so i wrote an VBScript for this purpose:
(But you can also google for touch.exe)

C:\Temp\set_mod_date.vbs

Dim WS, FSO, NET, ARGS, ArgFile, ArgDate
Set WS    = Wscript.CreateObject("WScript.Shell")
Set FSO   = Wscript.CreateObject("Scripting.FileSystemObject")
Set NET   = wscript.CreateObject("WScript.Network")
Set ARGS = WScript.Arguments

If ARGS.Count = 2 Then
        ArgFile = args.Item(0)
        ArgDate = args.Item(1)
Else
        MsgBox "Syntax:" & vbCRLF _
                & "VBTouch ""X:\Path\File.ext"" ""YYYY.MM.DD"""  & vbCRLF _
                & "VBTouch ""X:\Path\File.ext"" ""YYYY-MM-DD"""  & vbCRLF _
                & "VBTouch ""X:\Path\File.ext"" ""YYYY.MM.DD HH:MM"""  & vbCRLF _
                & "VBTouch ""X:\Path\File.ext"" ""DD.MM.YYYY HH:MM"""
        WScript.Quit
End IF
'msgbox ArgFile & " " & ArgDate

Call Touch(ArgFile, ArgDate)
'Call Touch("C:\1.aa", "31.12.2009 23:55")

Sub Touch(FolderPathFileName, NewDate)
On Error Resume Next
Dim Pos, FolderPath, FileName, app, folder, file
        If FSO.FileExists(FolderPathFileName) Then
                Pos = InstrRev (FolderPathFileName, "\")
                FolderPath = Left(FolderPathFileName, Pos)
                FileName = Mid (FolderPathFileName, Pos+1)
          Set app = CreateObject("Shell.Application")
          Set folder = app.NameSpace(FolderPath)
          Set file = folder.ParseName(FileName)

          file.ModifyDate = NewDate

          set file = nothing
          set folder = nothing
          set app = nothing
        Else
            'msgbox "File not found: " & FolderPathFileName
            WScript.Quit
        End IF
End Sub

3.) I use this PascalScript with ReNamer:

var
I: Integer;
Item, Name, Time: WideString;
dummy,cmd: String;
Parts: TStringsArray;

begin
    I := I + 1;
    Item := FileReadLine('C:\Temp\Names.txt', I);
    Parts := WideSplitString(Item, ',');
    Name := Parts[0];
    Time := Parts[1];

    IF (FileName=Name) Then
    begin
        cmd := 'cScript ' 
            + #34 + 'C:\Temp\set_mod_date.vbs' + #34
            + ' ' 
            + #34 + FilePath + #34 
            + ' ' 
            + #34 + Time + #34;
    //ShowMessage(cmd);
    ExecConsoleApp(cmd, dummy);
    end;
end.

4.) Load your files, execute the PascalScript Rule, and the modified date/time of the files in question are changed.

Last edited by Stefan (2010-07-15 22:50)


Read the  *WIKI* for HELP + MANUAL + Tips&Tricks.
If ReNamer had helped you, please *DONATE* to Denis or buy a PRO license. (Read *Lite vs Pro*)

Offline

#10 2010-07-14 20:50

SafetyCar
Senior Member
Registered: 2008-04-28
Posts: 446
Website

Re: A Timestamp problem: take from name and set on file

auwebio wrote:

The only problem is that I have to be extra-extra-careful with the input, making sure I always paste the exact number of dates and, most importantly, in the exact correspondence order of the files. Writing some automated check for the date input before I copy is easy; and I can always generate a file list with path and names (instead of dragging them to ReNamer); But, since there is no preview of the output before applying the script, the matching part between the files and the dates remain entirely dependent on me not "messing up" either in the order of the dates input or the number of them, etc.

So yo want a confirmation? What type? Yes/No dialog is easy to add but in fact


I'm assuming the user input then must be set to "Replace the current name" and "Skip extension" is unmarked then.
Since the objective is not really about changing the name this is completely fine  wink (setting the filename to be the full date with seconds as extension).

The extension is not a big deal, because the RegEx function will find the date anyway.


auwebio wrote:

I just must never (ever!) hit the Rename button.  lol
...
I did a tiny modification in the script so that I could still see the corresponding "new date" input after the preview, I hope you don't mind. (I also took out the :: and the >> from the final messages, as to avoid the "warning! found n invalid filename(s)!" message, which will now only appear if there's either no input for a file or exact same date for more than one file)

In the first sentence of the quote is the reason because I added those non-valid symbols  lol, but if you prefer changing them there is no problem for me.


auwebio wrote:

I was wondering if there shouldn't be a menu option to load file lists?

e.g.: File > Add List of Files

I think you are talking about this:
http://www.den4b.com/wiki/ReNamer:Menus … xport_menu



Some update on the code check if it's what you wanted.

var
  DateMod: TDateTime;
  DatePart: TStringsArray;
  Initialized, Cancel: Boolean;

begin
  // Ask for start
  If not initialized then
  begin
    Cancel := not WideDialogYesNo('Do yo want to start the date changes?');
    Initialized := True;
  end;

  If Cancel then Exit;
  
  // Date confirmation
  FileName := ReplaceRegEx(FileName, '^(.*(\d{4}-\d{1,2}-\d{1,2} \d{1,2}.\d{1,2}.\d{1,2}).*|.*)$', '$2', False, True);
  Cancel := not WideInputQuery('', 'Confirm the date for the file'+#10+#10+FilePath+#10, FileName);
  If Cancel then Exit;

  // Extract date parts
  DatePart := SubmatchesRegEx(FileName, '(\d{4})-(\d{1,2})-(\d{1,2}) (\d{1,2}).(\d{1,2}).(\d{1,2})', False);

  // Default message (File name will hold infomation messages)
  FileName := ':: ERROR >> No correct date found ::';

  // Continue if the date was found  
  If (length(DatePart)<>0) then
  begin
    // Try to build the date format
    If TryEncodeDate(StrToInt(DatePart[0]), StrToInt(DatePart[1]), StrToInt(DatePart[2]), DateMod) then
    begin
      DateMod := IncHour(DateMod, StrToInt(DatePart[3]));
      DateMod := IncMinute(DateMod, StrToInt(DatePart[4]));
      DateMod := IncSecond(DateMod, StrToInt(DatePart[5]));
      
      // Try to set the new time
      If SetFileTimeModified(FilePath, DateMod) then
        FileName := ':: OK >> Date changed succesfully ::'
      else
        FileName := ':: ERROR >> Date could not be changed ::';;
    end;
  end;
end.

Last edited by SafetyCar (2010-07-14 20:56)


If this software has helped you, consider getting your pro version. :)

Offline

Board footer

Powered by FluxBB