Say you have one file in your main media directory:
/phpGedView/media/filename.jpg
and another one in a subdirectory:
/phpGedView/media/dir/filename.jpg
When you try to delete the file in the main directory, it runs this sql:
SELECT * FROM pgv_media WHERE m_file LIKE '%filename.jpg'
thus marking both files for deletion.
This problem only occurs when deleting from the main media directory, if you try to delete the file from the subfolder it will run this sql:
SELECT * FROM pgv_media WHERE m_file LIKE '%dir/filename.jpg'
which matches the specific file you want it to.
This is a tough problem. The sql has to use a wildcard because when importing from outside of PGV the path stored in the GEDCOM might look like this:
c:/files/sources/filename.jpg
Does anyone see a way to solve this?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I do not undderstand your last comment: "when importing from outside of PGV the path stored in the GEDCOM might look like this:
c:/files/sources/filename.jpg".
Please elaborate.
The media in my GEDCOM file exported from PAF looks like:
1 OBJE
2 FORM jpg
2 FILE media\pictures\xxx\Per.jpg
2 TITL Per W
2 NOTE ...
I see it both in PAF and in PGV.
I had the same file name in two directories (media and media/admin)linked to two individuals.
I deleted the file M65 in media. (I did not delete first the media object.)
I87 - M64 in media/admin
I90 - M65 in media
I see
Media file successfully deleted.
Thumbnail file successfully deleted.
Record I90 successfully updated.
Record M65 successfully removed from GEDCOM.
Record M64 successfully removed from GEDCOM.
Update successful
According to this I87 is not updated?!?
I now see on the media tabs of the pages of I87 and I90 the media files M64 and M65 in a red box and an empty blue box.
For I90 M65 I do not see in the red box the media thumb.
For I87 I see the M64 thumb.
For I90 I see also
ERROR 8: Undefined index: M65
0 Error occurred on line 1306 of file functions_print_facts.php in function print_main_media
1 called from line 1246 of file individual_ctrl.php in function print_media_tab
2 called from line 984 of file individual_ctrl.php in function getTab
3 called from line 256 of file individual_ctrl.php in function init
4 called from line 2009 of file individual_ctrl.php in function require_once
5 called from line 29 of file individual.php
I now want to undo the changes.
I do not see I87 in the list to approve changes.
I undo the 3 other changes.
File M64 is returned to I87.
File of M65 was deleted, only the object remained.
I carried out the same sequence once before.
I think that the outcome was slightly different.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think that I have fixed this in the latest SVN 2162. I did a lot of testing and consolidated a LOT of old code. There is still way too much duplicated code in manage media to be to my liking, but I'll leave it for now.
The way I decided to fix this was to split the filenames on the / and then compare the number of slashes before the query with the number after the query. They should match exactly to make sure that the number of levels match and that no files in the subdirectory are deleted.
As an example, suppose you have c:/files/filename.jpg and c:/files/sources/filename.jpg on the server and you want to delete the c:/files/filename.jpg. This will cause a query to be generated as with %filename.jpg which will also match the filename in sources. But if we count the / in c:/files/filename.jpg we get 2 and if we count the / in c:/files/sources/filename.jpg we get 3 so they won't match then it won't get deleted.
This was a difficult problem to solve.
--John
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think that most of the time it wouldn't be a problem because it strips out the "media/" from the query before searching directory and should leave one of the slashes. But since the user can enter the value of the media directory, we can't guarantee that a slash will be there.
Also an even trickier case is if the files are spelled the same but the case is different:
/media/smith.jpg
/media/SMITH.jpg
Not a problem on Windows because it is case-insensitive, but *nix systems won't know the difference, and our SQL query is also case insensitive.
But I think I can solve both problems by checking if the filename is exactly the same. I have the exact filename because I have already split the paths on the /. So the check now becomes:
if (count($rlevels)==count($mlevels) && end($mlevels)==end($rlevels)) {
I have committed this to SVN 2163.
--John
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ah, you're right, there should still be a leading slash in the filename. But I like that extra check you added, it should catch all the edge cases and make absolutely sure nothing extra is deleted.
Great fix for this tough problem!
-larry
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When I export a GEDCOM from TMG my media filenames look like this:
d:/Documents and Settings/ljm/My Documents/ged/sources/beasley/beasley_fred_1876/beasley_fred_1876_beasleymen.jpg
My "Multi-Media directory levels to keep" is set to "2", so my PGV urls are:
/phpGedView/media/beasley/beasley_fred_1876/beasley_fred_1876_beasleymen.jpg
This means that the number of slashes don't match and this code never gets the chance to run:
if (count($rlevels)==count($mlevels) && end($mlevels)==end($rlevels)) {
if ($row["m_gedfile"]!=$GEDCOMS[$GEDCOM]["id"]) $onegedcom = false;
else $xrefs[] = $row["m_media"];
}
Would it make sense to bring MEDIA_DIRECTORY_LEVELS into the calculation? This *seems* to work:
$num_rlevels = count($rlevels);
if ($num_rlevels > ($MEDIA_DIRECTORY_LEVELS+2)) {$num_rlevels = $MEDIA_DIRECTORY_LEVELS+2;}
if ($num_rlevels==count($mlevels) && end($mlevels)==end($rlevels)) {
if ($row["m_gedfile"]!=$GEDCOMS[$GEDCOM]["id"]) $onegedcom = false;
else $xrefs[] = $row["m_media"];
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Since people can have their media directories in multiple places, would it be better to just leave off the +2? Anything greater than the MEDIA_DIRECTORY_LEVELS would be the same on the server anyway.
if ($num_rlevels > $MEDIA_DIRECTORY_LEVELS) {$num_rlevels =
$MEDIA_DIRECTORY_LEVELS;}
if ($num_mrlevels > $MEDIA_DIRECTORY_LEVELS) {$num_mlevels =
$MEDIA_DIRECTORY_LEVELS;}
if ($num_rlevels==$num_mlevels) && end($mlevels)==end($rlevels)) {
What do you think?
--John
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I don't think that will work; I am pretty sure this if statment will ALWAYS execute:
if ($num_mlevels > $MEDIA_DIRECTORY_LEVELS) {$num_mlevels = $MEDIA_DIRECTORY_LEVELS;}
Because mlevels is based on the full path to the media file (including the MEDIA_DIRECTORY, so +1 if your MEDIA_DIRECTORY is "media/") and it also includes the filename (so another +1)
For example, mlevels for this file:
media/beasley/beasley_fred_1876/beasley_fred_1876_beasleymen.jpg
is 4:
Array ( [0] => media [1] => beasley [2] => beasley_fred_1876 [3] => beasley_fred_1876_beasleymen.jpg )
(which is MEDIA_DIRECTORY_LEVELS + 2).
My +2 hack is therefore invalid too, if your MEDIA_DIRECTORY is set to something like "media/gedcom1/" you will need MEDIA_DIRECTORY_LEVELS +3.
this is a bit complex isn't it :)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I managed to remove just a media file from the root directory /media.
After I approved the deletion, I got a red error message that the media object does no longer exist.
I got rid of the message after I returned to the manage media list of the root directory.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Logged In: YES
user_id=45016
Originator: NO
I think I see how this could happen.
Say you have one file in your main media directory:
/phpGedView/media/filename.jpg
and another one in a subdirectory:
/phpGedView/media/dir/filename.jpg
When you try to delete the file in the main directory, it runs this sql:
SELECT * FROM pgv_media WHERE m_file LIKE '%filename.jpg'
thus marking both files for deletion.
This problem only occurs when deleting from the main media directory, if you try to delete the file from the subfolder it will run this sql:
SELECT * FROM pgv_media WHERE m_file LIKE '%dir/filename.jpg'
which matches the specific file you want it to.
This is a tough problem. The sql has to use a wildcard because when importing from outside of PGV the path stored in the GEDCOM might look like this:
c:/files/sources/filename.jpg
Does anyone see a way to solve this?
Logged In: YES
user_id=959928
Originator: YES
I do not undderstand your last comment: "when importing from outside of PGV the path stored in the GEDCOM might look like this:
c:/files/sources/filename.jpg".
Please elaborate.
The media in my GEDCOM file exported from PAF looks like:
1 OBJE
2 FORM jpg
2 FILE media\pictures\xxx\Per.jpg
2 TITL Per W
2 NOTE ...
I see it both in PAF and in PGV.
I had the same file name in two directories (media and media/admin)linked to two individuals.
I deleted the file M65 in media. (I did not delete first the media object.)
I87 - M64 in media/admin
I90 - M65 in media
I see
Media file successfully deleted.
Thumbnail file successfully deleted.
Record I90 successfully updated.
Record M65 successfully removed from GEDCOM.
Record M64 successfully removed from GEDCOM.
Update successful
According to this I87 is not updated?!?
I now see on the media tabs of the pages of I87 and I90 the media files M64 and M65 in a red box and an empty blue box.
For I90 M65 I do not see in the red box the media thumb.
For I87 I see the M64 thumb.
For I90 I see also
ERROR 8: Undefined index: M65
0 Error occurred on line 1306 of file functions_print_facts.php in function print_main_media
1 called from line 1246 of file individual_ctrl.php in function print_media_tab
2 called from line 984 of file individual_ctrl.php in function getTab
3 called from line 256 of file individual_ctrl.php in function init
4 called from line 2009 of file individual_ctrl.php in function require_once
5 called from line 29 of file individual.php
I now want to undo the changes.
I do not see I87 in the list to approve changes.
I undo the 3 other changes.
File M64 is returned to I87.
File of M65 was deleted, only the object remained.
I carried out the same sequence once before.
I think that the outcome was slightly different.
Logged In: YES
user_id=300048
Originator: NO
I think that I have fixed this in the latest SVN 2162. I did a lot of testing and consolidated a LOT of old code. There is still way too much duplicated code in manage media to be to my liking, but I'll leave it for now.
The way I decided to fix this was to split the filenames on the / and then compare the number of slashes before the query with the number after the query. They should match exactly to make sure that the number of levels match and that no files in the subdirectory are deleted.
As an example, suppose you have c:/files/filename.jpg and c:/files/sources/filename.jpg on the server and you want to delete the c:/files/filename.jpg. This will cause a query to be generated as with %filename.jpg which will also match the filename in sources. But if we count the / in c:/files/filename.jpg we get 2 and if we count the / in c:/files/sources/filename.jpg we get 3 so they won't match then it won't get deleted.
This was a difficult problem to solve.
--John
Logged In: YES
user_id=45016
Originator: NO
That's a very creative solution John!
There is one more problem area I thought of but didn't get a chance to add to the case notes here, and I think it might still be a problem.
Given these three files:
/media/johnsmith.jpg
/media/jacksmith.jpg
/media/smith.jpg
If you try to delete "smith.jpg", will it delete all three?
Logged In: YES
user_id=300048
Originator: NO
Good catch Larry!
I think that most of the time it wouldn't be a problem because it strips out the "media/" from the query before searching directory and should leave one of the slashes. But since the user can enter the value of the media directory, we can't guarantee that a slash will be there.
Also an even trickier case is if the files are spelled the same but the case is different:
/media/smith.jpg
/media/SMITH.jpg
Not a problem on Windows because it is case-insensitive, but *nix systems won't know the difference, and our SQL query is also case insensitive.
But I think I can solve both problems by checking if the filename is exactly the same. I have the exact filename because I have already split the paths on the /. So the check now becomes:
if (count($rlevels)==count($mlevels) && end($mlevels)==end($rlevels)) {
I have committed this to SVN 2163.
--John
Logged In: YES
user_id=45016
Originator: NO
Ah, you're right, there should still be a leading slash in the filename. But I like that extra check you added, it should catch all the edge cases and make absolutely sure nothing extra is deleted.
Great fix for this tough problem!
-larry
Logged In: YES
user_id=45016
Originator: NO
Hey John,
I don't think this is quite right yet.
When I export a GEDCOM from TMG my media filenames look like this:
d:/Documents and Settings/ljm/My Documents/ged/sources/beasley/beasley_fred_1876/beasley_fred_1876_beasleymen.jpg
My "Multi-Media directory levels to keep" is set to "2", so my PGV urls are:
/phpGedView/media/beasley/beasley_fred_1876/beasley_fred_1876_beasleymen.jpg
This means that the number of slashes don't match and this code never gets the chance to run:
if (count($rlevels)==count($mlevels) && end($mlevels)==end($rlevels)) {
if ($row["m_gedfile"]!=$GEDCOMS[$GEDCOM]["id"]) $onegedcom = false;
else $xrefs[] = $row["m_media"];
}
Would it make sense to bring MEDIA_DIRECTORY_LEVELS into the calculation? This *seems* to work:
$num_rlevels = count($rlevels);
if ($num_rlevels > ($MEDIA_DIRECTORY_LEVELS+2)) {$num_rlevels = $MEDIA_DIRECTORY_LEVELS+2;}
if ($num_rlevels==count($mlevels) && end($mlevels)==end($rlevels)) {
if ($row["m_gedfile"]!=$GEDCOMS[$GEDCOM]["id"]) $onegedcom = false;
else $xrefs[] = $row["m_media"];
}
Logged In: YES
user_id=300048
Originator: NO
Hi Larry,
Since people can have their media directories in multiple places, would it be better to just leave off the +2? Anything greater than the MEDIA_DIRECTORY_LEVELS would be the same on the server anyway.
if ($num_rlevels > $MEDIA_DIRECTORY_LEVELS) {$num_rlevels =
$MEDIA_DIRECTORY_LEVELS;}
if ($num_mrlevels > $MEDIA_DIRECTORY_LEVELS) {$num_mlevels =
$MEDIA_DIRECTORY_LEVELS;}
if ($num_rlevels==$num_mlevels) && end($mlevels)==end($rlevels)) {
What do you think?
--John
Logged In: YES
user_id=45016
Originator: NO
I don't think that will work; I am pretty sure this if statment will ALWAYS execute:
if ($num_mlevels > $MEDIA_DIRECTORY_LEVELS) {$num_mlevels = $MEDIA_DIRECTORY_LEVELS;}
Because mlevels is based on the full path to the media file (including the MEDIA_DIRECTORY, so +1 if your MEDIA_DIRECTORY is "media/") and it also includes the filename (so another +1)
For example, mlevels for this file:
media/beasley/beasley_fred_1876/beasley_fred_1876_beasleymen.jpg
is 4:
Array ( [0] => media [1] => beasley [2] => beasley_fred_1876 [3] => beasley_fred_1876_beasleymen.jpg )
(which is MEDIA_DIRECTORY_LEVELS + 2).
My +2 hack is therefore invalid too, if your MEDIA_DIRECTORY is set to something like "media/gedcom1/" you will need MEDIA_DIRECTORY_LEVELS +3.
this is a bit complex isn't it :)
Logged In: YES
user_id=300048
Originator: NO
What about if we drop the entire counting idea and just check all of the levels up to the media directory level in a loop:
$match = true;
$j=0;
for($i=count($rlevels)-1; $i>=0; $i--) {
if ($rlevels[$i] != $mlevels[$i]) {
$match = false;
break;
}
$j++;
if ($j>$MEDIA_DIRECTORY_LEVELS) break;
}
if ($match) {
if ($row["m_gedfile"]!=$GEDCOMS[$GEDCOM]["id"]) $onegedcom = false;
else $xrefs[] = $row["m_media"];
}
This will check that there is an exact match at each level up to MEDIA_DIRECTORY_LEVELS.
I've committed this solution. What do you think?
--John
Logged In: YES
user_id=45016
Originator: NO
Hi John,
When mlevels is something like this:
Array ( [0] => media [1] => bitterlich [2] => bitterlich_emil_1857 [3] => bitterlich_emil_1857_marriage_b_2.jpg )
And rlevels is something like this:
Array ( [0] => d: [1] => Documents and Settings [2] => ljm [3] => My Documents [4] => ged [5] => sources [6] => bitterlich [7] => bitterlich_emil_1857 [8] => bitterlich_emil_1857_marriage_b_2.jpg )
then this code:
if ($rlevels[$i] != $mlevels[$i])
throws this error:
ERROR 8: Undefined offset: 8
0 Error occurred on in function unknown
1 called from line 1044 of file media.php
However, this code works for me:
if ($rlevels[$i] != $mlevels[count($mlevels)-$j-1])
Does that line work for your test cases?
-larry
Logged In: YES
user_id=300048
Originator: NO
Oops. I forgot to test them switched around. I'll have to track the two sets differently.
Another new file is in SVN.
Thanks for you help to test this.
--John
Logged In: YES
user_id=45016
Originator: NO
looks good John!
Logged In: YES
user_id=959928
Originator: YES
I managed to remove just a media file from the root directory /media.
After I approved the deletion, I got a red error message that the media object does no longer exist.
I got rid of the message after I returned to the manage media list of the root directory.