From srdjan at catalyst.net.nz Thu Aug 1 01:41:32 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 1 Aug 2013 11:41:32 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] C4::Branch.pm needs unit tests Message-ID: <1375314092-30477-1-git-send-email-srdjan@catalyst.net.nz> From: Kenza Zaki Unit tests are wrap in a transaction. To test: prove t/db_dependent/Branch.t t/db_dependent/Branch.t .. 1/36 Using a hash as a reference is deprecated at t/db_dependent/Branch.t line 207. t/db_dependent/Branch.t .. ok All tests successful. Files=1, Tests=36, 1 wallclock secs ( 0.02 usr 0.02 sys + 0.13 cusr 0.01 csys = 0.18 CPU) Result: PASS http://bugs.koha-community.org/show_bug.cgi?id=10508 Signed-off-by: Srdjan --- t/db_dependent/Branch.t | 297 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 290 insertions(+), 7 deletions(-) diff --git a/t/db_dependent/Branch.t b/t/db_dependent/Branch.t index cc19f21..ffa2346 100644 --- a/t/db_dependent/Branch.t +++ b/t/db_dependent/Branch.t @@ -21,7 +21,7 @@ use Modern::Perl; use C4::Context; use Data::Dumper; -use Test::More tests => 6; +use Test::More tests => 36; use C4::Branch; @@ -30,6 +30,29 @@ BEGIN { use lib $FindBin::Bin; use_ok('C4::Branch'); } +can_ok( + 'C4::Branch', qw( + GetBranchCategory + GetBranchName + GetBranch + GetBranches + GetBranchesLoop + GetBranchDetail + get_branchinfos_of + ModBranch + CheckBranchCategorycode + GetBranchInfo + GetCategoryTypes + GetBranchCategories + GetBranchesInCategory + ModBranchCategoryInfo + DelBranch + DelBranchCategory + CheckCategoryUnique + mybranch + GetBranchesCount) +); + # Start transaction my $dbh = C4::Context->dbh; @@ -39,8 +62,127 @@ $dbh->{RaiseError} = 1; # clear the slate $dbh->do('DELETE FROM branchcategories'); -my @category_types = GetCategoryTypes(); -is_deeply(\@category_types, [ 'searchdomain', 'properties' ], 'received expected library category types'); +# Start test + +my $count = GetBranchesCount; +like( $count, '/^\d+$/', "the count is a number" ); + +#add 2 branches +my $b1 = { + add => 1, + branchcode => 'BRA', + branchname => 'BranchA', + branchaddress1 => 'adr1A', + branchaddress2 => 'adr2A', + branchaddress3 => 'adr3A', + branchzip => 'zipA', + branchcity => 'cityA', + branchstate => 'stateA', + branchcountry => 'countryA', + branchphone => 'phoneA', + branchfax => 'faxA', + branchemail => 'emailA', + branchurl => 'urlA', + branchip => 'ipA', + branchprinter => undef, + branchnotes => 'noteA', + opac_info => 'opacA' +}; +my $b2 = { + branchcode => 'BRB', + branchname => 'BranchB', + branchaddress1 => 'adr1B', + branchaddress2 => 'adr2B', + branchaddress3 => 'adr3B', + branchzip => 'zipB', + branchcity => 'cityB', + branchstate => 'stateB', + branchcountry => 'countryB', + branchphone => 'phoneB', + branchfax => 'faxB', + branchemail => 'emailB', + branchurl => 'urlB', + branchip => 'ipB', + branchprinter => undef, + branchnotes => 'noteB', + opac_info => 'opacB', +}; +ModBranch($b1); +is( ModBranch($b2), undef, 'the field add is missing' ); + +$b2->{add} = 1; +ModBranch($b2); +is( GetBranchesCount, $count + 2, "two branches added" ); + +#Test DelBranch + +is( DelBranch( $b2->{branchcode} ), 1, "One row affected" ); +is( GetBranchesCount, $count + 1, "branch BRB deleted" ); + +#Test GetBranchName +is( GetBranchName( $b1->{branchcode} ), + $b1->{branchname}, "GetBranchName returns the right name" ); + +#Test GetBranchDetail +my $branchdetail = GetBranchDetail( $b1->{branchcode} ); +$branchdetail->{add} = 1; +$b1->{issuing} = undef; # Not used in DB +is_deeply( $branchdetail, $b1, 'branchdetail is right' ); + +#Test Getbranches +my $branches = GetBranches; +is( scalar( keys %$branches ), + GetBranchesCount, "GetBranches returns the right number of branches" ); + +#Test ModBranch + +$b1 = { + branchcode => 'BRA', + branchname => 'BranchA modified', + branchaddress1 => 'adr1A modified', + branchaddress2 => 'adr2A modified', + branchaddress3 => 'adr3A modified', + branchzip => 'zipA modified', + branchcity => 'cityA modified', + branchstate => 'stateA modified', + branchcountry => 'countryA modified', + branchphone => 'phoneA modified', + branchfax => 'faxA modified', + branchemail => 'emailA modified', + branchurl => 'urlA modified', + branchip => 'ipA modified', + branchprinter => undef, + branchnotes => 'notesA modified', + opac_info => 'opacA modified' +}; + +ModBranch($b1); +is( GetBranchesCount, $count + 1, + "A branch has been modified, no new branch added" ); +$branchdetail = GetBranchDetail( $b1->{branchcode} ); +$b1->{issuing} = undef; +is_deeply( $branchdetail, $b1 , "GetBranchDetail gives the details of BRA"); + +#Test categories +my $categories = GetBranchCategories; +my $count_cat = scalar( keys $categories ); + +my $cat1 = { + add => 1, + categorycode => 'CAT1', + categoryname => 'catname1', + codedescription => 'catdesc1', + categorytype => 'cattype1', + show_in_pulldown => 1 +}; +my $cat2 = { + add => 1, + categorycode => 'CAT2', + categoryname => 'catname2', + categorytype => 'catype2', + codedescription => 'catdesc2', + show_in_pulldown => 1 +}; my %new_category = ( categorycode => 'LIBCATCODE', @@ -49,21 +191,162 @@ my %new_category = ( categorytype => 'searchdomain', show_in_pulldown => 1, ); + ModBranchCategoryInfo({ add => 1, %new_category, }); +ModBranchCategoryInfo($cat1); +ModBranchCategoryInfo($cat2); + +$categories = GetBranchCategories; +is( scalar( keys $categories ), $count_cat + 3, "Two categories added" ); +delete $cat1->{add}; +delete $cat2->{add}; +delete %new_category->{add}; +is_deeply($categories, [ $cat1,$cat2,\%new_category ], 'retrieve all expected library categories (bug 10515)'); + +#test GetBranchCategory +my $cat1detail = GetBranchCategory( $cat1->{categorycode} ); +delete $cat1->{add}; +is_deeply( $cat1detail, $cat1, 'CAT1 details are right' ); my $category = GetBranchCategory('LIBCATCODE'); is_deeply($category, \%new_category, 'fetched newly added library category'); +#Test DelBranchCategory +my $del = DelBranchCategory( $cat2->{categorycode} ); +is( $del, 1, 'One row affected' ); + +$categories = GetBranchCategories; +is( scalar( keys $categories ), $count_cat + 2, "Category CAT2 deleted" ); + +my $cat2detail = GetBranchCategory( $cat2->{categorycode} ); +is( $cat2detail, undef, 'CAT2 doesnt exist' ); + $category = GetBranchCategory(); is($category, undef, 'retrieve library category only if code is supplied (bug 10515)'); -my $categories = GetBranchCategories(); -is_deeply($categories, [ \%new_category ], 'retrieve all expected library categories (bug 10515)'); +#Test CheckBranchCategoryCode +my $check1 = CheckBranchCategorycode( $cat1->{categorycode} ); +my $check2 = CheckBranchCategorycode( $cat2->{categorycode} ); +like( $check1, '/^\d+$/', "CheckBranchCategorycode returns a number" ); + +$b2->{CAT1} = 1; +ModBranch($b2); +is( GetBranchesCount, $count + 2, 'BRB added' ); +is( + CheckBranchCategorycode( $cat1->{categorycode} ), + $check1 + 1, + 'BRB added to CAT1' +); + +#Test GetBranchInfo +my $b1info = GetBranchInfo( $b1->{branchcode} ); +$b1->{categories} = []; +is_deeply( @$b1info[0], $b1, 'BRA has no categories' ); + +my $b2info = GetBranchInfo( $b2->{branchcode} ); +my @cat = ( $cat1->{categorycode} ); +delete $b2->{add}; +delete $b2->{CAT1}; +$b2->{issuing} = undef; +$b2->{categories} = \@cat; +is_deeply( @$b2info[0], $b2, 'BRB has the category CAT1' ); + +ModBranchCategoryInfo({add => 1,%$cat2}); +$categories = GetBranchCategories; +is( scalar( keys $categories ), $count_cat + 3, "Two categories added" ); +$b2 = { + branchcode => 'BRB', + branchname => 'BranchB', + branchaddress1 => 'adr1B', + branchaddress2 => 'adr2B', + branchaddress3 => 'adr3B', + branchzip => 'zipB', + branchcity => 'cityB', + branchstate => 'stateB', + branchcountry => 'countryB', + branchphone => 'phoneB', + branchfax => 'faxB', + branchemail => 'emailB', + branchurl => 'urlB', + branchip => 'ipB', + branchprinter => undef, + branchnotes => 'noteB', + opac_info => 'opacB', + CAT1 => 1, + CAT2 => 1 +}; +ModBranch($b2); +$b2info = GetBranchInfo( $b2->{branchcode} ); +is( + CheckBranchCategorycode( $cat2->{categorycode} ), + $check2 + 1, + 'BRB added to CAT2' +); +push( @cat, $cat2->{categorycode} ); +delete $b2->{CAT1}; +delete $b2->{CAT2}; +$b2->{issuing} = undef; +$b2->{categories} = \@cat; +is_deeply( @$b2info[0], $b2, 'BRB has the category CAT1 and CAT2' ); + +#Test GetBranchesInCategory +my $brCat1 = GetBranchesInCategory( $cat1->{categorycode} ); +my @b = ( $b2->{branchcode} ); +is_deeply( $brCat1, \@b, 'CAT1 has branch BRB' ); + +my $b3 = { + add => 1, + branchcode => 'BRC', + branchname => 'BranchC', + branchaddress1 => 'adr1C', + branchaddress2 => 'adr2C', + branchaddress3 => 'adr3C', + branchzip => 'zipC', + branchcity => 'cityC', + branchstate => 'stateC', + branchcountry => 'countryC', + branchphone => 'phoneC', + branchfax => 'faxC', + branchemail => 'emailC', + branchurl => 'urlC', + branchip => 'ipC', + branchprinter => undef, + branchnotes => 'noteC', + opac_info => 'opacC', + CAT1 => 1, + CAT2 => 1 +}; +ModBranch($b3); +$brCat1 = GetBranchesInCategory( $cat1->{categorycode} ); +push( @b, $b3->{branchcode} ); +is_deeply( $brCat1, \@b, 'CAT1 has branch BRB and BRC' ); +is( + CheckBranchCategorycode( $cat1->{categorycode} ), + $check1 + 2, + 'BRC has been added to CAT1' +); + +#Test CheckCategoryUnique +is( CheckCategoryUnique('CAT2'), 0, 'CAT2 exists' ); +is( CheckCategoryUnique('CAT_NO_EXISTS'), 1, 'CAT_NO_EXISTS doesnt exist' ); + +#Test GetCategoryTypes +my @category_types = GetCategoryTypes(); +is_deeply(\@category_types, [ 'searchdomain', 'properties' ], 'received expected library category types'); $categories = GetBranchCategories(undef, undef, 'LIBCATCODE'); -is_deeply($categories, [ { %new_category, selected => 1 } ], 'retrieve expected, eselected library category (bug 10515)'); +is_deeply($categories, [ {%$cat1}, {%$cat2},{ %new_category, selected => 1 } ], 'retrieve expected, eselected library category (bug 10515)'); + +#TODO later: test mybranchine and onlymine +# Actually we cannot mock C4::Context->userenv in unit tests + +#Test GetBranchesLoop +my $loop = GetBranchesLoop; +is( scalar(@$loop), GetBranchesCount, 'There is the right number of branches' ); + +# End transaction +$dbh->rollback; -$dbh->rollback(); -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Aug 1 08:12:15 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 1 Aug 2013 18:12:15 +1200 Subject: [Koha-patches] [PATCH] Bug 10664 : Software error in overdue_notices.pl if there is no active currency Message-ID: <1375337535-9557-1-git-send-email-srdjan@catalyst.net.nz> From: Sophie Meynieux If there is no active currency, when running overdue_notices.pl you get a sofware error "Can't use an undefined value as a HASH reference" on GetCurrency() function call With this patch, if there is no active currency, fines are formated by default 0,00 and notices are correctly generated. Test plan : - have at least one borrower with overdue that should trigger a notice - verify that there is no active currency (Adminitration > Currency & Exchange rates) - run misc/cronjobs/overdue_notices.pl -v -n (to get the notice directly on output) => without the patch you get the software error => with the patch, notices are correctly generated If an active currency is defined, the script overdue_notices.pl runs the same with or without patch Signed-off-by: Srdjan --- misc/cronjobs/overdue_notices.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/misc/cronjobs/overdue_notices.pl b/misc/cronjobs/overdue_notices.pl index 5f285c0..04ccf5a 100755 --- a/misc/cronjobs/overdue_notices.pl +++ b/misc/cronjobs/overdue_notices.pl @@ -688,7 +688,8 @@ sub parse_letter { $tables{'branches'} = $p; } - my $currency_format = GetCurrency()->{currency}; + my $currencies = GetCurrency(); + my $currency_format = $currencies->{currency} if defined($currencies); my @item_tables; if ( my $i = $params->{'items'} ) { -- 1.8.1.2 From nengard at bywatersolutions.com Thu Aug 1 02:37:24 2013 From: nengard at bywatersolutions.com (Nicole C. Engard) Date: Wed, 31 Jul 2013 20:37:24 -0400 Subject: [Koha-patches] [PATCH] Bug 10671: Help files for course reserves Message-ID: <1375317444-3030-1-git-send-email-nengard@bywatersolutions.com> This patch adds the missing help files for course reserves. To test: * visit every page related to course reserves in the staff client * click help in the top right * review the help file for typos/content/links --- .../en/modules/help/course_reserves/add_items.tt | 15 ++++++++++++++ .../modules/help/course_reserves/course-details.tt | 11 ++++++++++ .../prog/en/modules/help/course_reserves/course.tt | 19 ++++++++++++++++++ .../help/course_reserves/course_reserves.tt | 21 ++++++++++++++++++++ 4 files changed, 66 insertions(+), 0 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/add_items.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course-details.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course_reserves.tt diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/add_items.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/add_items.tt new file mode 100644 index 0000000..776eb0c --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/add_items.tt @@ -0,0 +1,15 @@ +[% INCLUDE 'help-top.inc' %] + +

Add/edit course items

+ +

Before adding reserve materials you will need at least one course to add them to. To add materials visit the Course Reserves module.

+ +

Click on the title of the course you would like to add materials to.

+ +

At the top of the course description click the 'Add reserves' button to add titles to this reserve list. You will be asked to enter the barcode for the reserve item.

+ +

After you are done scanning the barcodes to add to the course you can see them on the course page.

+ +

See the full documentation for adding items to Course reserves in the manual (online).

+ +[% INCLUDE 'help-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course-details.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course-details.tt new file mode 100644 index 0000000..23dfca0 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course-details.tt @@ -0,0 +1,11 @@ +[% INCLUDE 'help-top.inc' %] + +

Course details

+ +

The course reserves module in Koha allows you to temporarily move items to 'reserve' and assign different circulation rules to these items while they are being used for a specific course.

+ +

The details page will show you the items you have on reserve for your course. From here you can add/remove items and edit the course.

+ +

See the full documentation for Course reserves in the manual (online).

+ +[% INCLUDE 'help-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course.tt new file mode 100644 index 0000000..e5ff376 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course.tt @@ -0,0 +1,19 @@ +[% INCLUDE 'help-top.inc' %] + +

Add/edit a course

+ +

Once you have completed your set up for Course Reserves you can start creating courses and adding titles to the reserve list.

+ +

From the main course reserves page you can add a new course by clicking the 'New course' button at the top left.

+ +

Your new course will need a Department, Number and Name at the bare minimum. You can also add in additional details like course section number and term. To link a instructor to this course simply start typing their name and Koha will search your patron database to find you the right person.

+ +

Once the instructor you want appears just click their name and they will be added. You can repeat this for all instructors on this course. Each instructor will appear above the search box and can be removed by clicking the 'Remove' link to the right of their name.

+ +

If you would like your course to show publicly you'll want to be sure to check the 'Enabled?' box before saving your new course.

+ +

Once your course is saved it will show on the main course reserves page and be searchable by any field in the course.

+ +

See the full documentation for adding Course reserves in the manual (online).

+ +[% INCLUDE 'help-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course_reserves.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course_reserves.tt new file mode 100644 index 0000000..9e8ab1c --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/course_reserves/course_reserves.tt @@ -0,0 +1,21 @@ +[% INCLUDE 'help-top.inc' %] + +

Course reserves

+ +

The course reserves module in Koha allows you to temporarily move items to 'reserve' and assign different circulation rules to these items while they are being used for a specific course.

+ +

Course Reserves Setup

+ +

Before using Course Reserves you will need to do some set up.

+ +

First you will need to enable course reserves by setting the UseCourseReserves preference to 'Use'.

+ +

Next you will need to have all of your course instructors added as patrons.

+ +

Next you will want to add a couple of new authorized values for Departments and Terms.

+ +

You may also want to create new item types, collection codes and/or shelving locations to make it clear that the items are on reserve to your patrons. You will also want to be sure to confirm that your circulation and fine rules are right for your new item types (whether they be hourly or daily loans).

+ +

See the full documentation for Course reserves in the manual (online).

+ +[% INCLUDE 'help-bottom.inc' %] -- 1.7.2.3 From oleonard at myacpl.org Thu Aug 1 15:23:10 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 1 Aug 2013 09:23:10 -0400 Subject: [Koha-patches] [PATCH] Bug 10656 - shelving locations not alpha on search Message-ID: <1375363390-3539-1-git-send-email-oleonard@myacpl.org> Collection codes and shelving locations are displayed in the OPAC and staff client via GetAuthorisedValues which currently sorts results by "lib, lib_opac." Consequently if lib (the description for the staff client) doesn't match lib_opac (the description for the OPAC) sorting will appear to be nonsensical in the OPAC. GetAuthorisedValues can be passed an $opac parameter, so this should be used to switch how reuslts are sorted. This patch implements such a switch. To test, modify your collection code or shelving location authorized values so that lib and lib_opac do not match. Set your AdvancedSearchTypes system preference to display the modified authorized values and view the advanced search page in the OPAC and staff client. Sorting should be correct in each case according to the correct value (lib in the staff client, lib_opac in the OPAC). --- C4/Koha.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/C4/Koha.pm b/C4/Koha.pm index ea8c2a6..1317006 100644 --- a/C4/Koha.pm +++ b/C4/Koha.pm @@ -1076,7 +1076,7 @@ sub GetAuthorisedValues { if(@where_strings > 0) { $query .= " WHERE " . join(" AND ", @where_strings); } - $query .= " GROUP BY lib ORDER BY category, lib, lib_opac"; + $query .= " GROUP BY lib ORDER BY category, " . ($opac ? "lib_opac, lib" : "lib, lib_opac"); my $sth = $dbh->prepare($query); -- 1.7.9.5 From oleonard at myacpl.org Thu Aug 1 16:14:04 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 1 Aug 2013 10:14:04 -0400 Subject: [Koha-patches] [PATCH] Bug 10619 - sco.css missing for CCSR OPAC templates Message-ID: <1375366444-4416-1-git-send-email-oleonard@myacpl.org> sco.css is not missing from CCSR, but some image paths in the CSS are incorrect, resulting in some missing images. This patch corrects those broken paths. This patch also hides the Cart/Lists/login region of the template which should not be visible in self checkout. To test, enable self-checkout and switch to the CCSR theme. Load a patron for self-checkout and confirm that images associated with buttons appear correctly: By the help link in the upper-right, on the 'Finish' button, etc. Try checking out an item which is already checked out to that patron to see more examples. --- koha-tmpl/opac-tmpl/ccsr/en/css/sco.css | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css b/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css index 5a79a47..d065fc6 100644 --- a/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css +++ b/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css @@ -140,27 +140,27 @@ div.message { .dialog input.back { - background : #FFF url(../../famfamfam/silk/arrow_left.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/arrow_left.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } .dialog input.return { - background : #FFF url(../../famfamfam/silk/book_previous.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/book_previous.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } .dialog input.renew { - background : #FFF url(../../famfamfam/silk/arrow_refresh.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/arrow_refresh.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } .dialog input.cancel { - background : #FFF url(../../famfamfam/silk/cancel.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/cancel.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } input.finish { - background : #dbe7ff url(../../famfamfam/silk/stop.png) no-repeat 4px center; + background : #dbe7ff url(/opac-tmpl/lib/famfamfam/silk/stop.png) no-repeat 4px center; border : 1px outset #666; padding : .2em .2em .2em 25px; } @@ -234,7 +234,7 @@ input.focus { border : 2px inset #336699; } #checkouthelp { - background : #FFF url("../../famfamfam/silk/help.png") no-repeat 4px center; + background : #FFF url("/opac-tmpl/lib/famfamfam/silk/help.png") no-repeat 4px center; padding : 3px 3px 3px 26px; position : absolute; top : 0; @@ -249,7 +249,7 @@ div.button a:link, div.button a:visited, div.button a:hover, div.button a:active { - background : #FFF url(../../famfamfam/silk/book_previous.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/book_previous.png) no-repeat 4px center; border : 1px outset #666; color : #000; padding : .4em .4em .4em 25px; @@ -339,3 +339,7 @@ span.lang{ div.ft { clear : both; } +#top-bar, +#main_footer { + display: none; +} \ No newline at end of file -- 1.7.9.5 From oleonard at myacpl.org Thu Aug 1 17:03:30 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 1 Aug 2013 11:03:30 -0400 Subject: [Koha-patches] [PATCH] Bug 10672 - Add subtitle to display of checkouts, overdues, and holds on the patron summary Message-ID: <1375369410-5217-1-git-send-email-oleonard@myacpl.org> In the OPAC, the patron summary page (opac-user.pl) should display subtitle along with title in the lists of checkouts, overdues, and holds. This patch adds it. To test, log in to the OPAC as a patron who has checkouts, overdues, and holds which include titles with subtitles. Titles should appear correctly with and without subtitles. --- koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 6 +++--- opac/opac-user.pl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt index d7c691f..f75c82c 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt @@ -179,7 +179,7 @@ $.tablesorter.addParser({ [% END %] - [% ISSUE.title |html %] + [% ISSUE.title |html %][% FOREACH subtitl IN ISSUE.subtitle %] [% subtitl.subfield %][% END %] [% ISSUE.author %] [% IF ( ISSUE.overdue ) %] @@ -325,7 +325,7 @@ $.tablesorter.addParser({ [% END %] [% END %] -[% OVERDUE.title |html %] [% OVERDUE.author %] +[% OVERDUE.title |html %][% FOREACH subtitl IN OVERDUE.subtitle %] [% subtitl.subfield %][% END %] [% OVERDUE.author %] [% UNLESS ( item_level_itypes ) %][% IF ( OVERDUE.imageurl ) %][% OVERDUE.description %][% END %] [% OVERDUE.description %][% END %] [% IF ( show_barcode ) %][% OVERDUE.barcode %][% END %] @@ -381,7 +381,7 @@ $.tablesorter.addParser({ [% ELSE %] [% END %] - [% RESERVE.reserves_title %] + [% RESERVE.reserves_title %][% FOREACH subtitl IN RESERVE.subtitle %] [% subtitl.subfield %][% END %] [% RESERVE.author %] [% RESERVE.reservedate | $KohaDates %] diff --git a/opac/opac-user.pl b/opac/opac-user.pl index 5c01ae2..731caf8 100755 --- a/opac/opac-user.pl +++ b/opac/opac-user.pl @@ -176,7 +176,7 @@ if ($issues){ } } $issue->{'charges'} = $charges; - + $issue->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($issue->{'biblionumber'}), GetFrameworkCode($issue->{'biblionumber'})); # check if item is renewable my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); ($issue->{'renewcount'},$issue->{'renewsallowed'},$issue->{'renewsleft'}) = GetRenewCount($borrowernumber, $issue->{'itemnumber'}); @@ -256,7 +256,7 @@ foreach my $res (@reserves) { if ( $res->{'expirationdate'} eq '0000-00-00' ) { $res->{'expirationdate'} = ''; } - + $res->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($res->{'biblionumber'}), GetFrameworkCode($res->{'biblionumber'})); $res->{'waiting'} = 1 if $res->{'found'} eq 'W'; $res->{'branch'} = $branches->{ $res->{'branchcode'} }->{'branchname'}; my $biblioData = GetBiblioData($res->{'biblionumber'}); -- 1.7.9.5 From oleonard at myacpl.org Thu Aug 1 20:46:12 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 1 Aug 2013 14:46:12 -0400 Subject: [Koha-patches] [PATCH 4/4] Bug 10402 [Template follow-up] Add multiple contacts for vendors Message-ID: <1375382772-7712-1-git-send-email-oleonard@myacpl.org> This template-only follow-up tweaks the button labels and restructures the vendor view layout a little bit to make it more amenable to multiple contacts: - Add spaces after button icons - Change "Add contact" to "Add another contact" in hopes of making it less ambiguous whether clicking it will submit the whole form. - Eliminate duplicate headers on the vendor view page by making the contact name the subheading for each individual contact. To test, view details for vendors with one or more contacts, and try editing to add additional contacts. Everything should look good and work correctly. --- .../prog/en/modules/acqui/supplier.tt | 76 +++++++++++--------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt index fcbaea4..7b92b6f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt @@ -16,11 +16,12 @@
  • - [% IF contact.id %]
  • [% END %] + [% IF contact.id %]
  • [% END %] [% END %] + [% BLOCK show_contact %] -

    Contact name: [% contact.name %]

    +

    [% contact.name %]

    Position: [% contact.position %]

    Phone: [% contact.phone %]

    Alternative phone: [% contact.altphone %]

    @@ -32,6 +33,7 @@

    Notes: [% contact.notes %]

    [% END %] [% END %] + [% INCLUDE 'doc-head-open.inc' %] Koha › Vendor [% bookselname %] @@ -149,7 +151,7 @@ function delete_contact() { [% INCLUDE edit_contact %] [% END %] - +
    @@ -259,41 +261,45 @@ function delete_contact() { [% IF ( accountnumber ) %]

    Account number: [% accountnumber %]

    [% END %] + +
    +

    Ordering information

    +

    Vendor is: + [% IF ( active ) %] + Active + [% ELSE %] + Inactive + [% END %]

    +

    List prices are: [% listprice %]

    +

    Invoice prices are: [% invoiceprice %]

    + [% IF ( gstrate ) %]

    Tax number registered: + [% IF ( gstreg ) %]Yes[% ELSE %]No[% END %]

    +

    List item price includes tax: + [% IF ( listincgst ) %]Yes[% ELSE %]No[% END %]

    +

    Invoice item price includes tax: + [% IF ( invoiceincgst ) %]Yes[% ELSE %]No[% END %]

    [% END %] +

    Discount: + [% discount | format("%.1f") %] %

    +

    Tax rate: + [% 0 + gstrate * 100 | format("%.1f") %] %

    + [% IF deliverytime.defined %] +

    Delivery time: + [% deliverytime %] days

    + [% END %] + [% IF ( notes ) %]

    Notes: + [% notes %]

    [% END %]
    - [% FOREACH contact IN contacts %] -
    -

    Contact details

    +
    + +
    +

    Contact

    + [% FOREACH contact IN contacts %] [% INCLUDE show_contact %] -
    - [% END %] -
    -
    -

    Ordering information

    -

    Vendor is: - [% IF ( active ) %] - Active - [% ELSE %] - Inactive - [% END %]

    -

    List prices are: [% listprice %]

    -

    Invoice prices are: [% invoiceprice %]

    - [% IF ( gstrate ) %]

    Tax number registered: - [% IF ( gstreg ) %]Yes[% ELSE %]No[% END %]

    -

    List item price includes tax: - [% IF ( listincgst ) %]Yes[% ELSE %]No[% END %]

    -

    Invoice item price includes tax: - [% IF ( invoiceincgst ) %]Yes[% ELSE %]No[% END %]

    [% END %] -

    Discount: - [% discount | format("%.1f") %] %

    -

    Tax rate: - [% 0 + gstrate * 100 | format("%.1f") %] %

    - [% IF deliverytime.defined %] -

    Delivery time: - [% deliverytime %] days

    - [% END %] - [% IF ( notes ) %]

    Notes: - [% notes %]

    [% END %] + [% END %] +
    + + [% IF ( contracts ) %]

    Contract(s)

    -- 1.7.9.5 From oleonard at myacpl.org Thu Aug 1 21:54:52 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 1 Aug 2013 15:54:52 -0400 Subject: [Koha-patches] [PATCH] Bug 10493 [Template follow-up] Add renewal script Message-ID: <1375386893-9061-1-git-send-email-oleonard@myacpl.org> This template followup fixes some minor template errors and adds some style to dialog buttons matching those seen on the circulation page. To test, submit barcodes to trigger the various error conditions: Non-existant barcode, over the renew limit, restricted patron, item on hold. Override and Ignore buttons should be properly styled and functional. --- .../intranet-tmpl/prog/en/modules/circ/renew.tt | 49 +++++++------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt index eba8892..fe090b5 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt @@ -8,16 +8,6 @@ [% INCLUDE 'doc-head-close.inc' %] - - @@ -25,56 +15,49 @@ $(document).ready(function () { [% INCLUDE 'header.inc' %] [% INCLUDE 'circ-search.inc' %] - +
    -
    -
    [% IF error %]

    Cannot renew:

    -

    + [% IF error == "no_item" %] - No item matches this barcode +

    No item matches this barcode

    [% ELSIF error == "no_checkout" %] - [% item.biblio.title %] [% item.biblioitem.subtitle %] - ( [% item.barcode %] ) - is not checked out to a patron. +

    [% item.biblio.title %] [% item.biblioitem.subtitle %] ( [% item.barcode %] ) is not checked out to a patron.

    [% ELSIF error == "too_many" %] - [% item.biblio.title %] [% item.biblioitem.subtitle %] ( [% item.barcode %] ) - has been renewed the maximum number of times by - [% borrower.firstname %] [% borrower.surname %] ( [% borrower.cardnumber %] ) +

    [% item.biblio.title %] [% item.biblioitem.subtitle %] ( [% item.barcode %] ) has been renewed the maximum number of times by [% borrower.firstname %] [% borrower.surname %] ( [% borrower.cardnumber %] )

    [% IF Koha.Preference('AllowRenewalLimitOverride') %] -
    + - +
    [% END %] [% ELSIF error == "on_reserve" %] - This item is on hold for other patrons. +

    This item is on hold for another patron.

    -
    + - +
    [% ELSIF error == "patron_restricted" %] - [% borrower.firstname %] [% borrower.surname %] ( [% borrower.cardnumber %] ) - is currently restricted. +

    [% borrower.firstname %] [% borrower.surname %] ( [% borrower.cardnumber %] ) is currently restricted.

    [% ELSE %] @@ -82,18 +65,18 @@ $(document).ready(function () { [% END %] - Ignore & continue -

    +
    + +
    [% END %] [% IF date_due %]
    +

    Item renewed:

    -

    Item renewed:

    - [% item.biblio.title %] [% item.biblioitem.subtitle %] - ( [% item.barcode %] ) + ( [% item.barcode %] ) renewed for [% borrower.firstname %] [% borrower.surname %] ( [% borrower.cardnumber %] ) now due on [% date_due | $KohaDates %] -- 1.7.9.5 From srdjan at catalyst.net.nz Fri Aug 2 01:53:32 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 2 Aug 2013 11:53:32 +1200 Subject: [Koha-patches] [PATCH] Bug 10628 - AutomaticItemReturn prevents holds queue from filling local holds with local items Message-ID: <1375401212-27223-1-git-send-email-srdjan@catalyst.net.nz> From: Kyle M Hall For some reason, C4::HoldsQueue::MapItemsToHoldRequests uses the system preference AutomaticItemReturn to decide if an attempt to fill local holds with local items. No explanation of this behavior is provided. Signed-off-by: Srdjan --- C4/HoldsQueue.pm | 13 ++++++++----- t/db_dependent/HoldsQueue.t | 11 +++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/C4/HoldsQueue.pm b/C4/HoldsQueue.pm index 2052f09..eff3148 100755 --- a/C4/HoldsQueue.pm +++ b/C4/HoldsQueue.pm @@ -32,6 +32,7 @@ use C4::Biblio; use C4::Dates qw/format_date/; use List::Util qw(shuffle); +use List::MoreUtils qw(any); use Data::Dumper; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); @@ -354,8 +355,6 @@ sub MapItemsToHoldRequests { return unless scalar(@$hold_requests) > 0; return unless scalar(@$available_items) > 0; - my $automatic_return = C4::Context->preference("AutomaticItemReturn"); - # identify item-level requests my %specific_items_requested = map { $_->{itemnumber} => 1 } grep { defined($_->{itemnumber}) } @@ -419,7 +418,7 @@ sub MapItemsToHoldRequests { my $pickup_branch = $request->{branchcode} || $request->{borrowerbranch}; my ($itemnumber, $holdingbranch); - my $holding_branch_items = $automatic_return ? undef : $items_by_branch{$pickup_branch}; + my $holding_branch_items = $items_by_branch{$pickup_branch}; if ( $holding_branch_items ) { foreach my $item (@$holding_branch_items) { if ( $request->{borrowerbranch} eq $item->{homebranch} ) { @@ -587,10 +586,14 @@ sub least_cost_branch { #$from - arrayref my ($to, $from, $transport_cost_matrix) = @_; -# Nothing really spectacular: supply to branch, a list of potential from branches -# and find the minimum from - to value from the transport_cost_matrix + # Nothing really spectacular: supply to branch, a list of potential from branches + # and find the minimum from - to value from the transport_cost_matrix return $from->[0] if @$from == 1; + # If the pickup library is in the list of libraries to pull from, + # return that library right away, it is obviously the least costly + return ($to) if any { $_ eq $to } @$from; + my ($least_cost, @branch); foreach (@$from) { my $cell = $transport_cost_matrix->{$to}{$_}; diff --git a/t/db_dependent/HoldsQueue.t b/t/db_dependent/HoldsQueue.t index 8de2583..5c4c74b 100755 --- a/t/db_dependent/HoldsQueue.t +++ b/t/db_dependent/HoldsQueue.t @@ -12,7 +12,7 @@ use C4::Context; use Data::Dumper; -use Test::More tests => 18; +use Test::More tests => 16; use C4::Branch; use C4::ItemType; @@ -100,7 +100,7 @@ my $priority = 1; # Make a reserve AddReserve ( $borrower_branchcode, $borrowernumber, $biblionumber, $constraint, $bibitems, $priority ); # $resdate, $expdate, $notes, $title, $checkitem, $found -$dbh->do("UPDATE reserves SET reservedate = reservedate - 1"); +$dbh->do("UPDATE reserves SET reservedate = DATE_SUB( reservedate, INTERVAL 1 DAY )"); # Tests my $use_cost_matrix_sth = $dbh->prepare("UPDATE systempreferences SET value = ? WHERE variable = 'UseTransportCostMatrix'"); @@ -121,8 +121,6 @@ $dbh->do("DELETE FROM items WHERE homebranch = '$borrower_branchcode' AND holdin # test_queue will flush C4::Context->set_preference('AutomaticItemReturn', 1); # Not sure how to make this test more difficult - holding branch does not matter -test_queue ('take from holdingbranch AutomaticItemReturn on', 0, $borrower_branchcode, undef); -test_queue ('take from holdingbranch AutomaticItemReturn on', 1, $borrower_branchcode, $least_cost_branch_code); $dbh->do("DELETE FROM tmp_holdsqueue"); $dbh->do("DELETE FROM hold_fill_targets"); @@ -148,6 +146,11 @@ ok( $queue_item && $queue_item->{holdingbranch} eq $least_cost_branch_code, "GetHoldsQueueItems" ) or diag( "Expected item for pick $borrower_branchcode, hold $least_cost_branch_code, got ".Dumper($queue_item) ); +ok( + C4::HoldsQueue::least_cost_branch( 'B', [ 'A', 'B', 'C' ] ) eq 'B', + 'C4::HoldsQueue::least_cost_branch returns the local branch if it is in the list of branches to pull from' +); + # XXX All this tests are for borrower branch pick-up. # Maybe needs expanding to homebranch or holdingbranch pick-up. -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Aug 2 04:48:17 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 2 Aug 2013 14:48:17 +1200 Subject: [Koha-patches] [PATCH] Bug 10672 - Add subtitle to display of checkouts, overdues, and holds on the patron summary Message-ID: <1375411697-13749-1-git-send-email-srdjan@catalyst.net.nz> From: Owen Leonard In the OPAC, the patron summary page (opac-user.pl) should display subtitle along with title in the lists of checkouts, overdues, and holds. This patch adds it. To test, log in to the OPAC as a patron who has checkouts, overdues, and holds which include titles with subtitles. Titles should appear correctly with and without subtitles. Signed-off-by: Srdjan --- koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 6 +++--- opac/opac-user.pl | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt index d7c691f..f75c82c 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt @@ -179,7 +179,7 @@ $.tablesorter.addParser({ [% END %] - [% ISSUE.title |html %] + [% ISSUE.title |html %][% FOREACH subtitl IN ISSUE.subtitle %] [% subtitl.subfield %][% END %] [% ISSUE.author %] [% IF ( ISSUE.overdue ) %] @@ -325,7 +325,7 @@ $.tablesorter.addParser({ [% END %] [% END %] -[% OVERDUE.title |html %] [% OVERDUE.author %] +[% OVERDUE.title |html %][% FOREACH subtitl IN OVERDUE.subtitle %] [% subtitl.subfield %][% END %] [% OVERDUE.author %] [% UNLESS ( item_level_itypes ) %][% IF ( OVERDUE.imageurl ) %][% OVERDUE.description %][% END %] [% OVERDUE.description %][% END %] [% IF ( show_barcode ) %][% OVERDUE.barcode %][% END %] @@ -381,7 +381,7 @@ $.tablesorter.addParser({ [% ELSE %] [% END %] - [% RESERVE.reserves_title %] + [% RESERVE.reserves_title %][% FOREACH subtitl IN RESERVE.subtitle %] [% subtitl.subfield %][% END %] [% RESERVE.author %] [% RESERVE.reservedate | $KohaDates %] diff --git a/opac/opac-user.pl b/opac/opac-user.pl index 5c01ae2..731caf8 100755 --- a/opac/opac-user.pl +++ b/opac/opac-user.pl @@ -176,7 +176,7 @@ if ($issues){ } } $issue->{'charges'} = $charges; - + $issue->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($issue->{'biblionumber'}), GetFrameworkCode($issue->{'biblionumber'})); # check if item is renewable my ($status,$renewerror) = CanBookBeRenewed( $borrowernumber, $issue->{'itemnumber'} ); ($issue->{'renewcount'},$issue->{'renewsallowed'},$issue->{'renewsleft'}) = GetRenewCount($borrowernumber, $issue->{'itemnumber'}); @@ -256,7 +256,7 @@ foreach my $res (@reserves) { if ( $res->{'expirationdate'} eq '0000-00-00' ) { $res->{'expirationdate'} = ''; } - + $res->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($res->{'biblionumber'}), GetFrameworkCode($res->{'biblionumber'})); $res->{'waiting'} = 1 if $res->{'found'} eq 'W'; $res->{'branch'} = $branches->{ $res->{'branchcode'} }->{'branchname'}; my $biblioData = GetBiblioData($res->{'biblionumber'}); -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Aug 2 05:25:24 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 2 Aug 2013 15:25:24 +1200 Subject: [Koha-patches] [PATCH] Bug 10619 - sco.css missing for CCSR OPAC templates Message-ID: <1375413924-17717-1-git-send-email-srdjan@catalyst.net.nz> From: Owen Leonard sco.css is not missing from CCSR, but some image paths in the CSS are incorrect, resulting in some missing images. This patch corrects those broken paths. This patch also hides the Cart/Lists/login region of the template which should not be visible in self checkout. To test, enable self-checkout and switch to the CCSR theme. Load a patron for self-checkout and confirm that images associated with buttons appear correctly: By the help link in the upper-right, on the 'Finish' button, etc. Try checking out an item which is already checked out to that patron to see more examples. Signed-off-by: Srdjan --- koha-tmpl/opac-tmpl/ccsr/en/css/sco.css | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css b/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css index 5a79a47..d065fc6 100644 --- a/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css +++ b/koha-tmpl/opac-tmpl/ccsr/en/css/sco.css @@ -140,27 +140,27 @@ div.message { .dialog input.back { - background : #FFF url(../../famfamfam/silk/arrow_left.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/arrow_left.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } .dialog input.return { - background : #FFF url(../../famfamfam/silk/book_previous.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/book_previous.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } .dialog input.renew { - background : #FFF url(../../famfamfam/silk/arrow_refresh.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/arrow_refresh.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } .dialog input.cancel { - background : #FFF url(../../famfamfam/silk/cancel.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/cancel.png) no-repeat 4px center; padding : .4em .4em .4em 25px; } input.finish { - background : #dbe7ff url(../../famfamfam/silk/stop.png) no-repeat 4px center; + background : #dbe7ff url(/opac-tmpl/lib/famfamfam/silk/stop.png) no-repeat 4px center; border : 1px outset #666; padding : .2em .2em .2em 25px; } @@ -234,7 +234,7 @@ input.focus { border : 2px inset #336699; } #checkouthelp { - background : #FFF url("../../famfamfam/silk/help.png") no-repeat 4px center; + background : #FFF url("/opac-tmpl/lib/famfamfam/silk/help.png") no-repeat 4px center; padding : 3px 3px 3px 26px; position : absolute; top : 0; @@ -249,7 +249,7 @@ div.button a:link, div.button a:visited, div.button a:hover, div.button a:active { - background : #FFF url(../../famfamfam/silk/book_previous.png) no-repeat 4px center; + background : #FFF url(/opac-tmpl/lib/famfamfam/silk/book_previous.png) no-repeat 4px center; border : 1px outset #666; color : #000; padding : .4em .4em .4em 25px; @@ -339,3 +339,7 @@ span.lang{ div.ft { clear : both; } +#top-bar, +#main_footer { + display: none; +} \ No newline at end of file -- 1.8.1.2 From tomascohen at gmail.com Fri Aug 2 20:39:04 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Fri, 2 Aug 2013 15:39:04 -0300 Subject: [Koha-patches] [PATCH] Bug 10678 - Allow framework selection when creating from Z39.50 Message-ID: <1375468744-18906-1-git-send-email-tomascohen@gmail.com> If we are creating a new record, we are forced to use the default framework and then change it after we have the cataloguing form filled. This patch adds the option to choose (from a splitted button dropdown) which framework to use. To test: - Apply the patch. - Go to More > Cataloguing - Check there's a nice split button that says "New from Z39.50" a) Click the button, the usual Z39.50 search popup should appear and work as expected (check the URL parameters and see frameworkcode= has no value b) Click on the dropdown arrow, choose a framework and the usual Z39.50 search popup should appear, this time frameworkcode= should have the chosen value. Regards To+ Sponsored-by: Universidad Nacional de Cordoba --- .../prog/en/modules/cataloguing/addbooks.tt | 26 +++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt index 9155235..6de5e51 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbooks.tt @@ -10,18 +10,23 @@ PopupZ3950(); return false; }); + + $(".z3950searchFw").click(function(){ + PopupZ3950($(this).prop('id')); + return false; + }); }); /* this function open a popup to search on z3950 server. */ - function PopupZ3950() { - var strQuery = GetZ3950Terms(); + function PopupZ3950(fw) { + var strQuery = GetZ3950Terms(fw); if(strQuery){ window.open("/cgi-bin/koha/cataloguing/z3950_search.pl?biblionumber=[% biblionumber %]"+strQuery,"z3950search",'width=760,height=450,location=yes,toolbar=no,scrollbars=yes,resize=yes'); } } /* provide Z3950 search points */ - function GetZ3950Terms(){ - var strQuery="&frameworkcode="; + function GetZ3950Terms(fw){ + var strQuery="&frameworkcode=" + fw; [% FOREACH z3950_search_param IN z3950_search_params %] strQuery += "&" + "[% z3950_search_param.name %]" + "=" + "[% z3950_search_param.encvalue %]"; [% END %] @@ -52,7 +57,18 @@ [% END %]
    - +
    + + + +
    [% END %] -- 1.8.1.2 From oleonard at myacpl.org Fri Aug 2 20:45:21 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 2 Aug 2013 14:45:21 -0400 Subject: [Koha-patches] [PATCH] Bug 7257 - Add a link to remove an individual title from a list Message-ID: <1375469121-12254-1-git-send-email-oleonard@myacpl.org> It should be possible when viewing the contents of a list to click a link to remove an individual title from the list without having to check a checkbox and click another button. This patch adds a link to each list item to "Remove from this list." The functionality is JavaScript-dependent, automatically checking the appropriate checkbox and submitting the form to delete. To test, view a list for which you have delete permission. There should be a "Remove from this list" link next to each item on the list. Test delete functionality by: - Clicking the link and then clicking cancel. - Clicking the link and confirming. - Checking more than one checkbox and then clicking a single remove link (only the one corresponding record should be removed). - Checking one or more checkboxes and clicking the "Remove from list" link at the top of the page. If JavaScript is disabled the links should not appear. There are now two delete confirmation messages: One if you're removing only one item, another if you're removing more than one. This is true whether you use the links or the checkboxes. --- koha-tmpl/opac-tmpl/prog/en/css/opac.css | 14 +++++++++++- .../opac-tmpl/prog/en/modules/opac-shelves.tt | 24 ++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/koha-tmpl/opac-tmpl/prog/en/css/opac.css b/koha-tmpl/opac-tmpl/prog/en/css/opac.css index 6fd9a90..f6198d2 100644 --- a/koha-tmpl/opac-tmpl/prog/en/css/opac.css +++ b/koha-tmpl/opac-tmpl/prog/en/css/opac.css @@ -779,6 +779,7 @@ a.tag_add { text-decoration : none; padding-left : 33px; } + /* Search results place hold link */ #placehold input.submit { background-image: url("../../images/sprite.png"); /* Place hold */ @@ -1491,7 +1492,8 @@ padding-left : .4em; .actions a.addtocart, .actions a.addtoshelf, .actions a.addtolist, -.actions a.tag_add { +.actions a.tag_add, +.actions a.removefromlist { margin-left : 1em; text-decoration : none; } @@ -1513,6 +1515,16 @@ padding-left : .4em; display : none; } +/* List contents remove from list link */ +.removefromlist { + background-image : url("../../images/sprite.png"); /* Delete */ + background-position : -8px -690px; + background-repeat: no-repeat; + text-decoration : none; + padding-left : 15px; + display : none; +} + /* Search results rows save to lists */ .actions a.addtoshelf { background-image : url("../../images/sprite.png"); /* MARC view */ diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tt index c9c0bca..4fe14db 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tt @@ -7,6 +7,7 @@ + [% END %] - @@ -71,7 +92,7 @@ [% IF ( line.amountoutstanding > 0 ) %] - + [% END %] @@ -111,9 +132,9 @@
    - + - + Cancel
    -- 1.7.9.5 From tomascohen at gmail.com Fri Aug 9 20:52:11 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Fri, 9 Aug 2013 15:52:11 -0300 Subject: [Koha-patches] [PATCH] Bug 8507: koha-create should be updated to use DOM indexing for bib Message-ID: <1376074332-28674-1-git-send-email-tomascohen@gmail.com> This patch makes the koha-create script install the file zebra-biblios-dom.cfg with the proper string substitutions inside on the new instance koha-conf.xml file. It also adds two option switches that control the indexing mode for the instance: --biblio-idx {dom|grs1} --auth-idx {dom|grs1} DOM indexing is set as the default for both authorities and bibliographic records. Following drojf (thanks!) advise I arranged stuff like explained here: http://wiki.koha-community.org/wiki/Switching_to_dom_indexing To test: - Apply the patch - Build your own packages and install them on a test server a) Create a new instance without using the new switches like: $ koha-create --create-db domtest - Check there's a file /etc/koha/sites/domtest/zebra-biblios-dom.cfg - Check that /etc/koha/sites/domtest/koha-conf.xml points to: * zebra-biblios-dom.cfg (biblioserver section) * zebra-biblios-dom.cfg (publicserver section) * zebra-authorities-dom.cfg (authorityserver section) - Success means the new default is DOM b) Play with the 4 possible combination of option switches $ koha-create --create-db --auth-idx grs1 --biblio-idx grs1 domtest $ koha-create --create-db --auth-idx grs1 --biblio-idx dom domtest $ koha-create --create-db --auth-idx dom --biblio-idx grs1 domtest $ koha-create --create-db --auth-idx dom --biblio-idx dom domtest - Check the koha-conf.xml file reflects the chosen options. c) Run $ koha-create --help - It should advertise this addition accordingly. d) Run $ man koha-create - Man page for koha-create should provide good information on the new switches behaviour Regards To+ Sponsored-by: Universidad Nacional de Cordoba --- debian/docs/koha-create.xml | 16 ++++ debian/scripts/koha-create | 113 +++++++++++++++++++++++- debian/scripts/koha-remove | 2 + debian/templates/koha-conf-site.xml.in | 33 +++---- debian/templates/zebra-biblios-dom-site.cfg.in | 22 ++--- 5 files changed, 158 insertions(+), 28 deletions(-) diff --git a/debian/docs/koha-create.xml b/debian/docs/koha-create.xml index 491da62..31c168a 100644 --- a/debian/docs/koha-create.xml +++ b/debian/docs/koha-create.xml @@ -27,6 +27,8 @@ ||| marc21|normarc|unimarc en|es|fr|nb|ru|uk + dom|grs1 + dom|grs1 /path/to/some.sql /path/to/config /path/to/passwd @@ -109,6 +111,20 @@ + + + + Specified the desired indexing mode for authority records. Valid options are (default) and . + + + + + + + Specified the desired indexing mode for bibliographic records. Valid options are (default) and . + + + diff --git a/debian/scripts/koha-create b/debian/scripts/koha-create index a0a830a..e8b2578 100755 --- a/debian/scripts/koha-create +++ b/debian/scripts/koha-create @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # koha-create -- Create a new Koha instance. # Copyright 2010 Catalyst IT, Ltd @@ -22,6 +22,7 @@ set -e usage="Usage: $0 [--create-db|--request-db|--populate-db|--use-db] \ [--marcflavor marc21|normarc|unimarc] \ [--zebralang en|es|fr|nb|ru|uk] \ + [--auth-idx dom|grs1] [--biblio-idx dom|grs1] \ [--defaultsql /path/to/some.sql] \ [--configfile /path/to/config] [--passwdfile /path/to/passwd] \ [--database database] [--adminuser n] instancename" @@ -45,6 +46,14 @@ generate_config_file() { -e "s/__ZEBRA_PASS__/$zebrapwd/g" \ -e "s/__ZEBRA_MARC_FORMAT__/$ZEBRA_MARC_FORMAT/g" \ -e "s/__ZEBRA_LANGUAGE__/$ZEBRA_LANGUAGE/g" \ + -e "s/__BIBLIOS_INDEXING_MODE__/$BIBLIOS_INDEXING_MODE/g" \ + -e "s/__AUTHORITIES_INDEXING_MODE__/$AUTHORITIES_INDEXING_MODE/g" \ + -e "s/__ZEBRA_BIBLIOS_CFG__/$ZEBRA_BIBLIOS_CFG/g" \ + -e "s/__ZEBRA_AUTHORITIES_CFG__/$ZEBRA_AUTHORITIES_CFG/g" \ + -e "s/__START_BIBLIOS_RETRIEVAL_INFO__/`echo $START_BIBLIOS_RETRIEVAL_INFO`/g" \ + -e "s/__END_BIBLIOS_RETRIEVAL_INFO__/`echo $END_BIBLIOS_RETRIEVAL_INFO`/g" \ + -e "s/__START_AUTHORITIES_RETRIEVAL_INFO__/`echo $START_AUTHORITIES_RETRIEVAL_INFO`/g" \ + -e "s/__END_AUTHORITIES_RETRIEVAL_INFO__/`echo $END_AUTHORITIES_RETRIEVAL_INFO`/g" \ -e "s/__DB_NAME__/$mysqldb/g" \ -e "s/__DB_HOST__/$mysqlhost/g" \ -e "s/__DB_USER__/$mysqluser/g" \ @@ -53,6 +62,7 @@ generate_config_file() { -e "s/__UNIXGROUP__/$username/g" \ -e "s/__PLUGINS_DIR__/\/var\/lib\/koha\/$name\/plugins/g" \ "/etc/koha/$1" > "$2" + } getmysqlhost() { @@ -75,6 +85,75 @@ getinstancemysqldatabase() { xmlstarlet sel -t -v 'yazgfs/config/database' "/etc/koha/sites/$1/koha-conf.xml" } +set_biblios_indexing_mode() +{ + local indexing_mode=$1 + local marc_format=$2 + + case $indexing_mode in + "dom") + START_BIBLIOS_RETRIEVAL_INFO=`cat <\n + \n + +EOF` + + END_BIBLIOS_RETRIEVAL_INFO=`cat <\n + <\/xi:fallback>\n + <\/xi:include> +EOF` + BIBLIOS_INDEXING_MODE="dom" + ZEBRA_BIBLIOS_CFG="zebra-biblios-dom.cfg" + ;; + "grs1") + START_BIBLIOS_RETRIEVAL_INFO=" " + END_BIBLIOS_RETRIEVAL_INFO=" <\/retrievalinfo>" + BIBLIOS_INDEXING_MODE="grs1" + ZEBRA_BIBLIOS_CFG="zebra-biblios.cfg" + ;; + *) + die "Error: '$indexing_mode' is not a valid indexing mode for bibliographic records." + ;; + esac +} + + +set_authorities_indexing_mode() +{ + local indexing_mode=$1 + local marc_format=$2 + + case $indexing_mode in + "dom") + START_AUTHORITIES_RETRIEVAL_INFO=`cat <\n + \n + +EOF` + + END_AUTHORITIES_RETRIEVAL_INFO=`cat <\n + <\/xi:fallback>\n + <\/xi:include>\n +EOF` + AUTHORITIES_INDEXING_MODE="dom" + ZEBRA_AUTHORITIES_CFG="zebra-authorities-dom.cfg" + ;; + "grs1") + START_AUTHORITIES_RETRIEVAL_INFO=" " + END_AUTHORITIES_RETRIEVAL_INFO=" <\/retrievalinfo>" + AUTHORITIES_INDEXING_MODE="grs1" + ZEBRA_AUTHORITIES_CFG="zebra-authorities.cfg" + ;; + *) + die "Error: '$indexing_mode' is not a valid indexing mode for authority records." + ;; + esac +} + # Set defaults and read config file, if it exists. DOMAIN="" OPACPORT="80" @@ -88,6 +167,16 @@ ZEBRA_MARC_FORMAT="marc21" ZEBRA_LANGUAGE="en" ADMINUSER="1" PASSWDFILE="/etc/koha/passwd" + +# Indexing mode variables (default is DOM) +BIBLIOS_INDEXING_MODE="dom" +AUTHORITIES_INDEXING_MODE="dom" + +START_BIBLIOS_RETRIEVAL_INFO="" +END_BIBLIOS_RETRIEVAL_INFO="" +START_AUTHORITIES_RETRIEVAL_INFO="" +END_AUTHORITIES_RETRIEVAL_INFO="" + if [ -e /etc/koha/koha-sites.conf ] then . /etc/koha/koha-sites.conf @@ -95,7 +184,7 @@ fi [ $# -ge 2 ] && [ $# -le 16 ] || die $usage -TEMP=`getopt -o crpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,marcflavor:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser: \ +TEMP=`getopt -o crpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,marcflavor:,auth-idx:,biblio-idx:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser: \ -n "$0" -- "$@"` # Note the quotes around `$TEMP': they are essential! @@ -106,6 +195,9 @@ CLO_ZEBRA_MARC_FORMAT="" CLO_ZEBRA_LANGUAGE="" CLO_DEFAULTSQL="" CLO_ADMINUSER="" +CLO_BIBLIOS_INDEXING_MODE="" +CLO_AUTHORITIES_INDEXING_MODE="" + while true ; do case "$1" in @@ -115,6 +207,8 @@ while true ; do -u|--use-db) op=use ; shift ;; -m|--marcflavor) CLO_ZEBRA_MARC_FORMAT="$2" ; shift 2 ;; -l|--zebralang) CLO_ZEBRA_LANGUAGE="$2" ; shift 2 ;; + --auth-idx) CLO_AUTHORITIES_INDEXING_MODE="$2" ; shift 2 ;; + --biblio-idx) CLO_BIBLIOS_INDEXING_MODE="$2" ; shift 2 ;; -d|--defaultsql) CLO_DEFAULTSQL="$2" ; shift 2 ;; -f|--configfile) configfile="$2" ; shift 2 ;; -s|--passwdfile) CLO_PASSWDFILE="$2" ; shift 2 ;; @@ -158,6 +252,19 @@ then PASSWDFILE="$CLO_PASSWDFILE" fi +if [ "$CLO_BIBLIOS_INDEXING_MODE" != "" ]; then + BIBLIOS_INDEXING_MODE=$CLO_BIBLIOS_INDEXING_MODE +fi + +set_biblios_indexing_mode $BIBLIOS_INDEXING_MODE $ZEBRA_MARC_FORMAT + + +if [ "$CLO_AUTHORITIES_INDEXING_MODE" != "" ]; then + AUTHORITIES_INDEXING_MODE=$CLO_AUTHORITIES_INDEXING_MODE +fi + +set_authorities_indexing_mode $AUTHORITIES_INDEXING_MODE $ZEBRA_MARC_FORMAT + name="$1" opacdomain="$OPACPREFIX$name$OPACSUFFIX$DOMAIN" @@ -261,6 +368,8 @@ eof # Generate and install Zebra config files. generate_config_file zebra-biblios-site.cfg.in \ "/etc/koha/sites/$name/zebra-biblios.cfg" + generate_config_file zebra-biblios-dom-site.cfg.in \ + "/etc/koha/sites/$name/zebra-biblios-dom.cfg" generate_config_file zebra-authorities-site.cfg.in \ "/etc/koha/sites/$name/zebra-authorities.cfg" generate_config_file zebra-authorities-dom-site.cfg.in \ diff --git a/debian/scripts/koha-remove b/debian/scripts/koha-remove index d68aebc..3fa5ef1 100755 --- a/debian/scripts/koha-remove +++ b/debian/scripts/koha-remove @@ -74,6 +74,8 @@ eof rm "/etc/koha/sites/$name/koha-conf.xml" [ -f "/etc/koha/sites/$name/zebra-biblios.cfg" ] && \ rm "/etc/koha/sites/$name/zebra-biblios.cfg" + [ -f "/etc/koha/sites/$name/zebra-biblios-dom.cfg" ] && \ + rm "/etc/koha/sites/$name/zebra-biblios-dom.cfg" [ -f "/etc/koha/sites/$name/zebra-authorities.cfg" ] && \ rm "/etc/koha/sites/$name/zebra-authorities.cfg" [ -f "/etc/koha/sites/$name/zebra-authorities-dom.cfg" ] && \ diff --git a/debian/templates/koha-conf-site.xml.in b/debian/templates/koha-conf-site.xml.in index ab8aff5..80da24a 100644 --- a/debian/templates/koha-conf-site.xml.in +++ b/debian/templates/koha-conf-site.xml.in @@ -18,7 +18,7 @@ tcp:@:__MERGE_SERVER_PORT__ /var/lib/koha/__KOHASITE__/biblios - /var/lib/koha/__KOHASITE__/zebra-biblios.cfg + /var/lib/koha/__KOHASITE__/__ZEBRA_BIBLIOS_CFG__ /var/lib/koha/__KOHASITE__/pqf.properties --> @@ -26,9 +26,10 @@ /var/lib/koha/__KOHASITE__/biblios - /etc/koha/sites/__KOHASITE__/zebra-biblios.cfg + /etc/koha/sites/__KOHASITE__/__ZEBRA_BIBLIOS_CFG__ /etc/koha/zebradb/pqf.properties - + + __START_BIBLIOS_RETRIEVAL_INFO__ @@ -75,7 +76,8 @@ - + __END_BIBLIOS_RETRIEVAL_INFO__ + /var/lib/koha/__KOHASITE__/authorities - /etc/koha/sites/__KOHASITE__/zebra-authorities-dom.cfg + /etc/koha/sites/__KOHASITE__/__ZEBRA_AUTHORITIES_CFG__ /etc/koha/zebradb/pqf.properties - - - + + __START_AUTHORITIES_RETRIEVAL_INFO__ - - - + __END_AUTHORITIES_RETRIEVAL_INFO__ + + __BIBLIOS_INDEXING_MODE__ + __AUTHORITIES_INDEXING_MODE__ /etc/koha/searchengine/queryparser.yaml diff --git a/debian/templates/zebra-biblios-dom-site.cfg.in b/debian/templates/zebra-biblios-dom-site.cfg.in index a748ddd..88d0d6d 100644 --- a/debian/templates/zebra-biblios-dom-site.cfg.in +++ b/debian/templates/zebra-biblios-dom-site.cfg.in @@ -3,7 +3,7 @@ # $Id: zebra.cfg,v 1.1.2.2 2006/05/09 12:03:16 rangi Exp $ # # Where are the config files located? -profilePath:__ZEBRA_CONF_DIR__/biblios/etc:__ZEBRA_CONF_DIR__/etc:__ZEBRA_CONF_DIR__/marc_defs/__ZEBRA_MARC_FORMAT__/biblios:__ZEBRA_CONF_DIR__/lang_defs/__ZEBRA_LANGUAGE__:__ZEBRA_CONF_DIR__/xsl +profilePath:/etc/koha/zebradb/biblios/etc:/etc/koha/zebradb/etc:/etc/koha/zebradb/marc_defs/__ZEBRA_MARC_FORMAT__/biblios:/etc/koha/zebradb/lang_defs/__ZEBRA_LANGUAGE__:/etc/koha/zebradb/xsl # modulePath - where to look for loadable zebra modules modulePath: /usr/lib/idzebra-2.0/modules @@ -21,9 +21,9 @@ attset: gils.att # http://www.indexdata.dk/zebra/doc/zebra-cfg.tkl # http://www.indexdata.dk/zebra/doc/grs.tkl -recordtype: dom.__ZEBRA_CONF_DIR__/biblios/etc/dom-config.xml -marcxml.recordtype: dom.__ZEBRA_CONF_DIR__/biblios/etc/dom-config.xml -iso2709.recordtype: dom.__ZEBRA_CONF_DIR__/biblios/etc/dom-config-marc.xml +recordtype: dom./etc/koha/zebradb/biblios/etc/dom-config.xml +marcxml.recordtype: dom./etc/koha/zebradb/biblios/etc/dom-config.xml +iso2709.recordtype: dom./etc/koha/zebradb/biblios/etc/dom-config-marc.xml recordId: (bib1,Local-number) storeKeys:1 @@ -31,18 +31,18 @@ storeData:1 # Lock File Area -lockDir: __ZEBRA_LOCK_DIR__/biblios +lockDir: /var/lock/koha/__KOHASITE__/biblios perm.anonymous:ar -perm.__ZEBRA_USER__:rw -passwd: __ZEBRA_CONF_DIR__/etc/passwd -register: __ZEBRA_DATA_DIR__/biblios/register:20G -shadow: __ZEBRA_DATA_DIR__/biblios/shadow:20G +perm.kohauser:rw +passwd: /etc/koha/sites/__KOHASITE__/zebra.passwd +register: /var/lib/koha/__KOHASITE__/biblios/register:20G +shadow: /var/lib/koha/__KOHASITE__/biblios/shadow:20G # Temp File area for result sets -setTmpDir: __ZEBRA_DATA_DIR__/biblios/tmp +setTmpDir: /var/lib/koha/__KOHASITE__/biblios/tmp # Temp File area for index program -keyTmpDir: __ZEBRA_DATA_DIR__/biblios/key +keyTmpDir: /var/lib/koha/__KOHASITE__/biblios/key # Approx. Memory usage during indexing memMax: 50M -- 1.7.9.5 From oleonard at myacpl.org Mon Aug 12 14:38:55 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Mon, 12 Aug 2013 08:38:55 -0400 Subject: [Koha-patches] [PATCH] Bug 10614 - have add order form at top and bottom Message-ID: <1376311136-20073-1-git-send-email-oleonard@myacpl.org> If a basket has a lot of items it may be inconvenient to scroll to the bottom of the patch to reach the "add to basket" form. This patch adds as "Add to basket" button to the toolbar which uses JavaScript to copy the form into a modal dialog for quick access. To test, apply the patch and view an open basket. You should be able to click the "Add to basket" button to trigger a modal dialog with the full "Add to basket" list of options. All options in the list should function normally. If you view a closed basket the new button should not appear. --- .../intranet-tmpl/prog/en/modules/acqui/basket.tt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt index 84df886..8cbc46e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt @@ -28,6 +28,11 @@ $("#show_all_details").attr('checked', false); updateColumnsVisibility(false); + [% UNLESS ( closedate ) %] + $('#addtoBasket').on('show', function () { + $(this).find(".modal-body").html($("#acqui_basket_add")[0].outerHTML); + }); + [% END %] }); //]]> @@ -137,6 +142,7 @@ [% UNLESS ( selectbasketg ) %] [% UNLESS ( closedate ) %]
    + [% IF ( unclosable ) %] @@ -451,6 +457,15 @@ [% END %]
    [% UNLESS ( closedate ) %] + + + + [% INCLUDE 'acquisitions-add-to-basket.inc' %] [% END %] [% END %] -- 1.7.9.5 From colin.campbell at ptfs-europe.com Mon Aug 12 17:47:14 2013 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Mon, 12 Aug 2013 16:47:14 +0100 Subject: [Koha-patches] [PATCH] Bug 10712: Save missing config variables to install log Message-ID: <1376322434-16209-1-git-send-email-colin.campbell@ptfs-europe.com> The variables for AUTH_INDEX_MODE and ZEBRA_TOKENIZER were not being saved to the koha_install_log file. As a result when using the --prev-install-log option in Makefile.PL the user was still prompted to select these This patch adds the appropriate variables to the list saved in the install log --- misc/koha-install-log | 2 ++ rewrite-config.PL | 1 + 2 files changed, 3 insertions(+) diff --git a/misc/koha-install-log b/misc/koha-install-log index d842484..17dd0da 100644 --- a/misc/koha-install-log +++ b/misc/koha-install-log @@ -57,6 +57,8 @@ INSTALL_ZEBRA=__INSTALL_ZEBRA__ INSTALL_SRU=__INSTALL_SRU__ INSTALL_PAZPAR2=__INSTALL_PAZPAR2__ BIB_INDEX_MODE=__BIB_INDEX_MODE__ +AUTH_INDEX_MODE=__AUTH_INDEX_MODE__ +ZEBRA_TOKENIZER=__ZEBRA_TOKENIZER__ RUN_DATABASE_TESTS=__RUN_DATABASE_TESTS__ PATH_TO_ZEBRA=__PATH_TO_ZEBRA__ USE_MEMCACHED=__USE_MEMCACHED__ diff --git a/rewrite-config.PL b/rewrite-config.PL index 90fd5ff..e903d49 100644 --- a/rewrite-config.PL +++ b/rewrite-config.PL @@ -122,6 +122,7 @@ $prefix = $ENV{'INSTALL_BASE'} || "/usr"; '__ZEBRA_RUN_DIR__' => "$prefix/var/run/zebradb", '__ZEBRA_MARC_FORMAT__' => 'marc21', '__ZEBRA_LANGUAGE__' => 'en', + '__ZEBRA_TOKENIZER__' => 'chr', '__ZEBRA_TOKENIZER_STMT__' => 'charmap word-phrase-utf.chr', '__ZEBRA_AUTH_CFG__' => 'zebra-authorities.cfg', '__ZEBRA_BIB_CFG__' => 'zebra-biblios.cfg', -- 1.8.4.rc2.15.g96cb27a From oleonard at myacpl.org Mon Aug 12 21:13:16 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Mon, 12 Aug 2013 15:13:16 -0400 Subject: [Koha-patches] [PATCH] Bug 8324 - Redisplay OPAC list with correct sort after edit Message-ID: <1376334797-24225-1-git-send-email-oleonard@myacpl.org> If you are viewing the contents of a list, edit it, change the default sort, and save your list will be redisplayed sorted by title no matter what default sort you chose. Lists do not automatically sort by their default sort, they must be opened with the sort parameter. This patch adds the list's sort parameter to the redirect after editing. To test, open an existing list in the OPAC which contains items. Click the "Edit list" link at the top of the list contents view. Change the default sort to something new. Click "Save." If the list is redisplayed using the new default sort the patch worked. --- C4/VirtualShelves/Page.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/C4/VirtualShelves/Page.pm b/C4/VirtualShelves/Page.pm index 7756d92..90f0f3f 100644 --- a/C4/VirtualShelves/Page.pm +++ b/C4/VirtualShelves/Page.pm @@ -200,7 +200,7 @@ sub shelfpage { } if($displaymode eq "viewshelf"){ - print $query->redirect( $pages{$type}->{redirect} . "?viewshelf=$shelfnumber" ); + print $query->redirect( $pages{$type}->{redirect} . "?viewshelf=$shelfnumber" . "&sortfield=" . $shelf->{sortfield}); } elsif($displaymode eq "publicshelves"){ print $query->redirect( $pages{$type}->{redirect} ); } else { -- 1.7.9.5 From oleonard at myacpl.org Mon Aug 12 21:34:52 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Mon, 12 Aug 2013 15:34:52 -0400 Subject: [Koha-patches] [PATCH] Bug 10714 - Redirect to list contents view upon save after initiating edit from list contents view Message-ID: <1376336092-24532-1-git-send-email-oleonard@myacpl.org> In the staff client, if you initiate a list edit from the list contents view you should be redirected to that same view after saving your changes. The OPAC already works this way. To test, view the contents of an existing list. Click the "Edit list" item under the "Edit" menu. Click save on the list edit form and you should be redirected back to the contents view of that list. --- .../prog/en/includes/virtualshelves-toolbar.inc | 2 +- .../prog/en/modules/virtualshelves/shelves.tt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc index 225e5dd..4de9e19 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc @@ -38,7 +38,7 @@
    -
    + -
    Import -
    + + + + Import + + -
    + @@ -239,39 +259,56 @@ function Check(f) { Edit Delete -
    Export -
    -
    -
    - Export framework - -
      -
    1. -
    2. -
    3. -
    4. -
    -
    -
    Cancel
    + + + Export + +
    -
    -
    Import -
    -
    -
    - Import [% frameworkcode %] framework structure (fields and subfields) from a spreadsheet file (.csv, .xml, .ods) or SQL file - - -
      -
    1. -
    -
    -
    Cancel
    -
    -
    -
    + + + + Import + + [% END %] -- 1.7.9.5 From tomascohen at gmail.com Thu Aug 15 00:30:46 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Wed, 14 Aug 2013 19:30:46 -0300 Subject: [Koha-patches] [PATCH 1/2] Bug 10733: Memcached on package installs Message-ID: <1376519447-20446-1-git-send-email-tomascohen@gmail.com> This patch makes the koha-create script adjust the koha-conf.xml file with the proper string substitutions to enable the use of memcached for the created Koha instance. It adds three option switches that control this: --use-memcached (defaults to "no") --memcached-servers "host1:port1,..." (defaults to 127.0.0.1:11211) --memcached-namespace "desired_namespace" (defaults to koha_${instance}) Note: the docs discourage setting user's own namespace. Using memcached is off as the default. The relevant configuration variables will remain empty if the user doesn't pass --use-memcached to the command. It matches the current behaviour. To test: - Apply the patch - Build your own packages and install them on a test server a) Create a new instance without using the new switches like: $ koha-create --create-db memctest - Check that /etc/koha/sites/memctest/koha-conf.xml contains: * Empty tag. * Empty tag. b) Play with the possible combination of option switches (Note that the code defaults to empty and will remain like that if --use-memcached is not used, so less tests...) $ koha-create --create-db --use-memcached memctest $ koha-create --create-db --use-memcached --memcached-servers "anything:xxx" memctest $ koha-create --create-db --use-memcached --memcached-servers "anything:xxx" --memcached-namespace "something" memctest $ koha-create --create-db --use-memcached --memcached-namespace "something" memctest - Check the koha-conf.xml file reflects the chosen options. c) Run $ koha-create --help - It should advertise this addition accordingly. d) Run $ man koha-create - Man page for koha-create should provide good information on the new switches behaviour Enjoy To+ Sponsored-by: Universidad Nacional de Cordoba --- debian/docs/koha-create.xml | 24 ++++++++++++++++++ debian/scripts/koha-create | 45 ++++++++++++++++++++++++++++++++-- debian/templates/koha-conf-site.xml.in | 4 +-- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/debian/docs/koha-create.xml b/debian/docs/koha-create.xml index 31c168a..0781fd3 100644 --- a/debian/docs/koha-create.xml +++ b/debian/docs/koha-create.xml @@ -29,6 +29,9 @@ en|es|fr|nb|ru|uk dom|grs1 dom|grs1 + + server:port + koha_namespace /path/to/some.sql /path/to/config /path/to/passwd @@ -125,6 +128,27 @@ + + + + Make the Koha instance use memcached. . + + + + + + + Specify a comma-separated list of host:port memcached servers for using with the created Koha instance. Defaults to , the needed configuration for a locally installed memcached server. + + + + + + + Specifiy a memcached for the created Koha instance. You usually leave this option alone to avoid namespace collisions. It defaults to . + + + diff --git a/debian/scripts/koha-create b/debian/scripts/koha-create index e8b2578..bcfadc9 100755 --- a/debian/scripts/koha-create +++ b/debian/scripts/koha-create @@ -61,6 +61,8 @@ generate_config_file() { -e "s/__UNIXUSER__/$username/g" \ -e "s/__UNIXGROUP__/$username/g" \ -e "s/__PLUGINS_DIR__/\/var\/lib\/koha\/$name\/plugins/g" \ + -e "s/__MEMCACHED_NAMESPACE__/$MEMCACHED_NAMESPACE/g" \ + -e "s/__MEMCACHED_SERVERS__/$MEMCACHED_SERVERS/g" \ "/etc/koha/$1" > "$2" } @@ -154,6 +156,26 @@ EOF` esac } + +set_memcached() +{ + local instance="$1" + + if [ "$CLO_MEMCACHED_SERVERS" != "" ]; then + MEMCACHED_SERVERS=$CLO_MEMCACHED_SERVERS + else + MEMCACHED_SERVERS=$DEFAULT_MEMCACHED_SERVERS + fi + + if [ "$CLO_MEMCACHED_NAMESPACE" != "" ]; then + MEMCACHED_NAMESPACE=$CLO_MEMCACHED_NAMESPACE + else + # default + MEMCACHED_NAMESPACE="koha_$instance" + fi + +} + # Set defaults and read config file, if it exists. DOMAIN="" OPACPORT="80" @@ -167,6 +189,10 @@ ZEBRA_MARC_FORMAT="marc21" ZEBRA_LANGUAGE="en" ADMINUSER="1" PASSWDFILE="/etc/koha/passwd" +USE_MEMCACHED="no" +MEMCACHED_SERVERS="" +MEMCACHED_NAMESPACE="" +DEFAULT_MEMCACHED_SERVERS="127.0.0.1:11211" # Indexing mode variables (default is DOM) BIBLIOS_INDEXING_MODE="dom" @@ -184,7 +210,7 @@ fi [ $# -ge 2 ] && [ $# -le 16 ] || die $usage -TEMP=`getopt -o crpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,marcflavor:,auth-idx:,biblio-idx:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser: \ +TEMP=`getopt -o crpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,use-memcached,marcflavor:,auth-idx:,biblio-idx:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser:,memcached-servers:,memcached-namespace:, \ -n "$0" -- "$@"` # Note the quotes around `$TEMP': they are essential! @@ -197,6 +223,8 @@ CLO_DEFAULTSQL="" CLO_ADMINUSER="" CLO_BIBLIOS_INDEXING_MODE="" CLO_AUTHORITIES_INDEXING_MODE="" +CLO_MEMCACHED_SERVERS="" +CLO_MEMCACHED_NAMESPACE="" while true ; do @@ -204,7 +232,16 @@ while true ; do -c|--create-db) op=create ; shift ;; -r|--request-db) op=request ; shift ;; -p|--populate-db) op=populate ; shift ;; - -u|--use-db) op=use ; shift ;; + -u|--use-db) op=use ; shift ;; + --use-memcached) + USE_MEMCACHED="yes" + shift ;; + --memcached-servers) + CLO_MEMCACHED_SERVERS="$2" + shift 2 ;; + --memcached-namespace) + CLO_MEMCACHED_NAMESPACE="$2" + shift 2;; -m|--marcflavor) CLO_ZEBRA_MARC_FORMAT="$2" ; shift 2 ;; -l|--zebralang) CLO_ZEBRA_LANGUAGE="$2" ; shift 2 ;; --auth-idx) CLO_AUTHORITIES_INDEXING_MODE="$2" ; shift 2 ;; @@ -267,6 +304,10 @@ set_authorities_indexing_mode $AUTHORITIES_INDEXING_MODE $ZEBRA_MARC_FORMAT name="$1" +if [ "$USE_MEMCACHED" = "yes" ]; then + set_memcached $name +fi + opacdomain="$OPACPREFIX$name$OPACSUFFIX$DOMAIN" intradomain="$INTRAPREFIX$name$INTRASUFFIX$DOMAIN" diff --git a/debian/templates/koha-conf-site.xml.in b/debian/templates/koha-conf-site.xml.in index 71de9fb..9bf090b 100644 --- a/debian/templates/koha-conf-site.xml.in +++ b/debian/templates/koha-conf-site.xml.in @@ -276,8 +276,8 @@ /usr/share/koha/misc/koha-install-log 0 - - + __MEMCACHED_SERVERS__ + __MEMCACHED_NAMESPACE__ __BIBLIOS_INDEXING_MODE__ __AUTHORITIES_INDEXING_MODE__ /etc/koha/searchengine/queryparser.yaml -- 1.8.1.2 From tomascohen at gmail.com Thu Aug 15 00:30:47 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Wed, 14 Aug 2013 19:30:47 -0300 Subject: [Koha-patches] [PATCH 2/2] Bug 10733: add 'memcached' as suggested dependency In-Reply-To: <1376519447-20446-1-git-send-email-tomascohen@gmail.com> References: <1376519447-20446-1-git-send-email-tomascohen@gmail.com> Message-ID: <1376519447-20446-2-git-send-email-tomascohen@gmail.com> Adds 'memcached' to the control.in file so the user is suggested by apt to install it. Sponsored-by: Universidad Nacional de Cordoba --- debian/control.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/control.in b/debian/control.in index e2b8882..c3d463f 100644 --- a/debian/control.in +++ b/debian/control.in @@ -32,7 +32,8 @@ Depends: ${misc:Depends}, ${koha:Depends}, unzip, xmlstarlet, yaz -Suggests: mysql-server +Suggests: mysql-server, + memcached Homepage: http://koha-community.org/ Description: integrated (physical) library management system Koha is an Integrated Library Managment system for real-world libraries -- 1.8.1.2 From tomascohen at gmail.com Thu Aug 15 15:24:27 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Thu, 15 Aug 2013 10:24:27 -0300 Subject: [Koha-patches] [PATCH] Bug 10733: Follow-up - use koha-sites.conf Message-ID: <1376573067-6383-1-git-send-email-tomascohen@gmail.com> In order to respect the current schema, where configuration values are pondered like this: hardcoded < koha-sites.conf < koha-create option switches I changed the patch a bit. I even changed MEMCACHED_NAMESPACE for MEMCACHED_PREFIX that seems to fit better in the current schema. Any feedback is welcome. Regards To+ Sponsored-by: Universidad Nacional de Cordoba --- debian/docs/koha-create.xml | 28 +++++++++++++++++++++++++--- debian/scripts/koha-create | 32 ++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/debian/docs/koha-create.xml b/debian/docs/koha-create.xml index 0781fd3..61cf588 100644 --- a/debian/docs/koha-create.xml +++ b/debian/docs/koha-create.xml @@ -31,7 +31,7 @@ dom|grs1 server:port - koha_namespace + namespace_prefix /path/to/some.sql /path/to/config /path/to/passwd @@ -143,9 +143,9 @@ - + - Specifiy a memcached for the created Koha instance. You usually leave this option alone to avoid namespace collisions. It defaults to . + Specifiy a for memcached. You usually leave this option alone to avoid namespace collisions. It defaults to . @@ -219,6 +219,28 @@ + + + Valid values are and . If not present koha-create will default to . Also, this will be overriden by the switch. + + + + + + + A comma-separated list of valid memcached servers. Usually in the form of . If not present koha-create will default to . Also, this will be overriden by the arguments of the switch. + + + + + + + A prefix for all new Koha instances to use in memcached. If not present koha-create will default to . Also, this will be overriden by the arguments of the switch. + + + + + Specifies format of MARC records to be indexed by Zebra. Possible values are 'marc21', 'normarc' and 'unimarc'. diff --git a/debian/scripts/koha-create b/debian/scripts/koha-create index bcfadc9..d655ca2 100755 --- a/debian/scripts/koha-create +++ b/debian/scripts/koha-create @@ -23,6 +23,8 @@ usage="Usage: $0 [--create-db|--request-db|--populate-db|--use-db] \ [--marcflavor marc21|normarc|unimarc] \ [--zebralang en|es|fr|nb|ru|uk] \ [--auth-idx dom|grs1] [--biblio-idx dom|grs1] \ + [--use-memcached] \ + [--memcached-servers server:port] [--memcached-prefix prefix] \ [--defaultsql /path/to/some.sql] \ [--configfile /path/to/config] [--passwdfile /path/to/passwd] \ [--database database] [--adminuser n] instancename" @@ -164,14 +166,20 @@ set_memcached() if [ "$CLO_MEMCACHED_SERVERS" != "" ]; then MEMCACHED_SERVERS=$CLO_MEMCACHED_SERVERS else - MEMCACHED_SERVERS=$DEFAULT_MEMCACHED_SERVERS + if [ "$MEMCACHED_SERVERS" = "" ]; then + MEMCACHED_SERVERS=$DEFAULT_MEMCACHED_SERVERS + # else: was set by the koha-sites.conf file + fi fi - if [ "$CLO_MEMCACHED_NAMESPACE" != "" ]; then - MEMCACHED_NAMESPACE=$CLO_MEMCACHED_NAMESPACE + if [ "$CLO_MEMCACHED_PREFIX" != "" ]; then + MEMCACHED_NAMESPACE="$CLO_MEMCACHED_PREFIX"_"$instance" else - # default - MEMCACHED_NAMESPACE="koha_$instance" + if [ "$MEMCACHED_PREFIX" != "" ]; then + MEMCACHED_NAMESPACE="$MEMCACHED_PREFIX"_"$instance" + else + MEMCACHED_NAMESPACE="$DEFAULT_MEMCACHED_PREFIX"_"$instance" + fi fi } @@ -189,10 +197,14 @@ ZEBRA_MARC_FORMAT="marc21" ZEBRA_LANGUAGE="en" ADMINUSER="1" PASSWDFILE="/etc/koha/passwd" + +# memcached variables USE_MEMCACHED="no" MEMCACHED_SERVERS="" -MEMCACHED_NAMESPACE="" +MEMCACHED_PREFIX="" +# hardcoded memcached defaults DEFAULT_MEMCACHED_SERVERS="127.0.0.1:11211" +DEFAULT_MEMCACHED_PREFIX="koha_" # Indexing mode variables (default is DOM) BIBLIOS_INDEXING_MODE="dom" @@ -210,7 +222,7 @@ fi [ $# -ge 2 ] && [ $# -le 16 ] || die $usage -TEMP=`getopt -o crpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,use-memcached,marcflavor:,auth-idx:,biblio-idx:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser:,memcached-servers:,memcached-namespace:, \ +TEMP=`getopt -o crpm:l:d:f:b:a: -l create-db,request-db,populate-db,use-db,use-memcached,marcflavor:,auth-idx:,biblio-idx:,zebralang:,defaultsql:,configfile:,passwdfile:,database:,adminuser:,memcached-servers:,memcached-prefix:, \ -n "$0" -- "$@"` # Note the quotes around `$TEMP': they are essential! @@ -224,7 +236,7 @@ CLO_ADMINUSER="" CLO_BIBLIOS_INDEXING_MODE="" CLO_AUTHORITIES_INDEXING_MODE="" CLO_MEMCACHED_SERVERS="" -CLO_MEMCACHED_NAMESPACE="" +CLO_MEMCACHED_PREFIX="" while true ; do @@ -239,8 +251,8 @@ while true ; do --memcached-servers) CLO_MEMCACHED_SERVERS="$2" shift 2 ;; - --memcached-namespace) - CLO_MEMCACHED_NAMESPACE="$2" + --memcached-prefix) + CLO_MEMCACHED_PREFIX="$2" shift 2;; -m|--marcflavor) CLO_ZEBRA_MARC_FORMAT="$2" ; shift 2 ;; -l|--zebralang) CLO_ZEBRA_LANGUAGE="$2" ; shift 2 ;; -- 1.8.1.2 From oleonard at myacpl.org Thu Aug 15 16:19:44 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 15 Aug 2013 10:19:44 -0400 Subject: [Koha-patches] [PATCH] Bug 10661 - Mandatory item fields should be formatted the same on all forms Message-ID: <1376576384-10261-1-git-send-email-oleonard@myacpl.org> Mandatory item fields are not indicated the same way in all places. This patch corrects two places where required fields were shown in bold rather than using the standard "required" class: When adding an order from a staged file and when adding an item for a new issue of a serial. Unrelated changes: Added $KohaDates formatting of date and time and corrected capitalization on a heading on the add order from staged file page. It would be nice to be able to use the same method for displaying the item form as we use on neworderentry.tt -- pulling in the form from a separate include. However that system is designed for handling multiple items and would need to be adapted for these cases. To test, you must have a staged file from which to add an order. Open an existing basket or create a new one and choose to add an order "From a staged file." Choose a staged file from which to order. The item entry form under the "Import all" heading should show required fields in red. To test in serials: Begin the process for receiving an item from an existing subscription. On the serials-edit page, find the "Click to add item" links and click to open the item edit forms. There should be one under the numbered issue and the supplemental issue forms. In both cases the item edit screen should show the mandatory item fields in red. --- .../prog/en/modules/acqui/addorderiso2709.tt | 11 +++++++---- .../prog/en/modules/serials/serials-edit.tt | 14 ++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/addorderiso2709.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/addorderiso2709.tt index 3223dc2..78107d9 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/addorderiso2709.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/addorderiso2709.tt @@ -52,7 +52,7 @@
    [% IF ( batch_details ) %]

    Add orders from [% comments %] - ([% file_name %] staged on [% upload_timestamp %]) + ([% file_name %] staged on [% upload_timestamp | $KohaDates with_hours => 1 %])

    @@ -123,7 +123,7 @@
    [% IF ( import_batch_id ) %]
    -

    Import All

    +

    Import all

    Import all the lines in the basket with the following parameters:

    @@ -148,8 +148,11 @@
      [% FOREACH iteminformatio IN item.iteminformation %]
    1. - - + [% IF (iteminformatio.mandatory) %] + + [% ELSE %] + + [% END %] [% iteminformatio.marc_value %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-edit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-edit.tt index 8f9ea5f..ecae99d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-edit.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-edit.tt @@ -236,8 +236,11 @@ $(document).ready(function() {
        [% FOREACH iteminformatio IN item.iteminformation %]
      1. - - + [% IF (iteminformatio.mandatory) %] + + [% ELSE %] + + [% END %] [% iteminformatio.marc_value %] @@ -344,8 +347,11 @@ $(document).ready(function() {
          [% FOREACH iteminformatio IN newserialloo.iteminformation %]
        1. - - + [% IF (iteminformatio.mandatory) %] + + [% ELSE %] + + [% END %] [% iteminformatio.marc_value %] -- 1.7.9.5 From oleonard at myacpl.org Thu Aug 15 18:29:51 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 15 Aug 2013 12:29:51 -0400 Subject: [Koha-patches] [PATCH] Bug 10737 - Add "Add to basket" link on vendor search results page Message-ID: <1376584192-11431-1-git-send-email-oleonard@myacpl.org> This patch adds an "add to basket" link to the vendor search results page for each open basket associated with each vendor. Clicking it triggers a modal window with the "add to basket" choices for that vendor and basket. Other changes in this patch: - "New basket" and "Receive shipment" buttons associated with each vendor search result have been converted to Bootstrap-styled buttons. - Basket closed date has been moved into its own column so that the table can be sorted by that value. - Table columns containing dates now use the "title-string" sort option, eliminating the need for a special date sorting algorithm. - Converted some &'s to &'s To test, apply the patch and search for a vendor. For each vendor in your search results baskets which are open should include an "add to basket" link. Clicking it should open a modal dialog with the same "add to basket" options offered on the basket page. The correct vendor ID and basket number should be associated with each link. The newly-styled "new basket" and "receive shipment" buttons should work correctly. Table sorting should work correctly, including the new "closed" column. --- .../prog/en/modules/acqui/booksellers.tt | 65 +++++++++++++++----- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt index 525ea66..a6e0591 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt @@ -14,17 +14,17 @@ [% END %] - Patron messaging preferences [% IF type_only %]

          If no preferences are selected, the default preferences for the category chosen will be applied on save, otherwise your selection here is saved

          [% END %] [% INCLUDE 'messaging-preference-form.inc' %] [% IF ( SMSSendDriver ) %]

          - [% IF ( opduplicate ) %] - - [% ELSE %] - - [% END %] +

          [% END %] -- 1.7.9.5 From srdjan at catalyst.net.nz Wed Aug 21 02:53:54 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Wed, 21 Aug 2013 12:53:54 +1200 Subject: [Koha-patches] [PATCH] Bug 10426 Remove unused sub GetCcodes from Koha.pm Message-ID: <1377046434-5895-1-git-send-email-srdjan@catalyst.net.nz> From: Colin Campbell Remove uncalled sub GetCcodes Also remove comment in opac-search.pl which is remaining reference to it and serves no useful purpose Signed-off-by: Srdjan --- C4/Koha.pm | 22 ---------------------- opac/opac-search.pl | 4 ---- 2 files changed, 26 deletions(-) diff --git a/C4/Koha.pm b/C4/Koha.pm index 6f91b8b..3fb5a70 100644 --- a/C4/Koha.pm +++ b/C4/Koha.pm @@ -41,7 +41,6 @@ BEGIN { &subfield_is_koha_internal_p &GetPrinters &GetPrinter &GetItemTypes &getitemtypeinfo - &GetCcodes &GetSupportName &GetSupportList &get_itemtypeinfos_of &getframeworks &getframeworkinfo @@ -286,27 +285,6 @@ END_SQL return get_infos_of( $query, 'itemtype', undef, \@itemtypes ); } -# this is temporary until we separate collection codes and item types -sub GetCcodes { - my $count = 0; - my @results; - my $dbh = C4::Context->dbh; - my $sth = - $dbh->prepare( - "SELECT * FROM authorised_values ORDER BY authorised_value"); - $sth->execute; - while ( my $data = $sth->fetchrow_hashref ) { - if ( $data->{category} eq "CCODE" ) { - $count++; - $results[$count] = $data; - - #warn "data: $data"; - } - } - $sth->finish; - return ( $count, @results ); -} - =head2 getauthtypes $authtypes = &getauthtypes(); diff --git a/opac/opac-search.pl b/opac/opac-search.pl index 7d2b7a6..76f4fda 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -246,10 +246,6 @@ foreach my $advanced_srch_type (@advanced_search_types) { } $template->param(advancedsearchesloop => \@advancedsearchesloop); -# # load the itypes (Called item types in the template -- just authorized values for searching) -# my ($itypecount, at itype_loop) = GetCcodes(); -# $template->param(itypeloop=>\@itype_loop,); - # The following should only be loaded if we're bringing up the advanced search template if ( $template_type && $template_type eq 'advsearch' ) { # load the servers (used for searching -- to do federated searching, etc.) -- 1.8.1.2 From oleonard at myacpl.org Wed Aug 21 16:59:42 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Wed, 21 Aug 2013 10:59:42 -0400 Subject: [Koha-patches] [PATCH] Bug 2693 - Tagging: Add filter by name Message-ID: <1377097182-22960-1-git-send-email-oleonard@myacpl.org> If you want to filter results on the tags management page by the reviewer you have to know their borrowernumber. It would be better to be able to search by name, but in the meantime this patch adds an autocomplete widget to the form field so that you can do a name search and populate the field with the borrowernumber. To test you must have approved or rejected tags. From the tags review page (tags/review.pl), view all, approved, or rejected tags. Type a name in the "reviewer" form field in the left sidebar filter. You should get an autocomplete dropdown with names matching your search. When you select one the form field should be populated by the borrowernumber. --- circ/ysearch.pl | 5 +++-- .../intranet-tmpl/prog/en/modules/tags/review.tt | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/circ/ysearch.pl b/circ/ysearch.pl index 8a48c51..c57bb38 100755 --- a/circ/ysearch.pl +++ b/circ/ysearch.pl @@ -44,7 +44,7 @@ if ($auth_status ne "ok") { } my $dbh = C4::Context->dbh; -my $sql = qq(SELECT surname, firstname, cardnumber, address, city, zipcode, country +my $sql = qq(SELECT borrowernumber, surname, firstname, cardnumber, address, city, zipcode, country FROM borrowers WHERE surname LIKE ? OR firstname LIKE ? @@ -58,7 +58,8 @@ print "["; my $i = 0; while ( my $rec = $sth->fetchrow_hashref ) { if($i > 0){ print ","; } - print "{\"surname\":\"" . $rec->{surname} . "\",\"" . + print "{\"borrowernumber\":\"" . $rec->{borrowernumber} . "\",\"" . + "surname\":\"".$rec->{surname} . "\",\"" . "firstname\":\"".$rec->{firstname} . "\",\"" . "cardnumber\":\"".$rec->{cardnumber} . "\",\"" . "address\":\"".$rec->{address} . "\",\"" . diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tags/review.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tags/review.tt index 89c998a..19f3e49 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tags/review.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tags/review.tt @@ -121,6 +121,21 @@ td input,td input[type="submit"] { font-size: 85%; padding: 1px; } $("*").ajaxError(function(evt, request, settings){ if ((alerted +=1) <= 1){ window.alert(_("AJAX error")+" (" + alerted + " alert)"); } }); + var reviewerField = $("#approver"); + reviewerField.autocomplete({ + source: "/cgi-bin/koha/circ/ysearch.pl", + minLength: 3, + select: function( event, ui ) { + reviewerField.val( ui.item.borrowernumber ); + return false; + } + }) + .data( "autocomplete" )._renderItem = function( ul, item ) { + return $( "
        2. " ) + .data( "item.autocomplete", item ) + .append( "" + item.surname + ", " + item.firstname + " (" + item.cardnumber + ") " + item.address + " " + item.city + " " + item.zipcode + " " + item.country + "" ) + .appendTo( ul ); + }; }); //]]> -- 1.7.9.5 From srdjan at catalyst.net.nz Fri Aug 23 06:36:32 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 23 Aug 2013 16:36:32 +1200 Subject: [Koha-patches] [PATCH] Bug 9611: Change the password hashing algorithm from MD5 to Bcrypt Message-ID: <1377232592-23400-1-git-send-email-srdjan@catalyst.net.nz> From: Srikanth Dhondi What this patch aims to accomplish? * All new passwords are stored as Bcrypt-hashes * For password verification: - If the user was created before this patch was applied then use MD5 to hash the entered password <-- backwards compatibility - If the user was created after this patch was applied then use Bcrypt to hash the entered password * Any password change made via the staff interface or the OPAC will be automatically Bcrypt-hashed; this applies to old users whose passwords were stored as MD5 hashes previously Test plan: 1) Add new users and check whether their passwords are stored as Bcrypt hashes or not. 2) To test that authentication works for both old as well as new users: a) Login as an existing user whose password is stored as a MD5 hash b) Login as an existing user whose password is stored as a Bcrypt hash 3) In the staff interface, change the password of an existing user whose password is stored as an MD5 hash a) Check the new password is stored as a Bcrypt-hash in the database b) Try to login with the new password 4) In the OPAC, verify that a) Old user with old pass can change password, new format b) New user with new pass can change password c) Old and new user with self-updated pass can login Whitespace cleanup was contributed by Bernardo Gonzalez Kriegel. Signed-off-by: Bernardo Gonzalez Kriegel Signed-off-by: Mason James Signed-off-by: Galen Charlton --- C4/Auth.pm | 54 +++++++++++++++++++++++++++++++++++++++++----- C4/Members.pm | 35 ++++++------------------------ members/member-password.pl | 2 +- opac/opac-passwd.pl | 13 ++++++++--- 4 files changed, 66 insertions(+), 38 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index 1e17e59..d0b17fd 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -23,6 +23,8 @@ use Digest::MD5 qw(md5_base64); use JSON qw/encode_json decode_json/; use URI::Escape; use CGI::Session; +use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64); +use Crypt::Random::Source; require Exporter; use C4::Context; @@ -47,7 +49,7 @@ BEGIN { @ISA = qw(Exporter); @EXPORT = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions); @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &get_all_subpermissions &get_user_subpermissions - ParseSearchHistoryCookie + ParseSearchHistoryCookie hash_password ); %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] ); $ldap = C4::Context->config('useldapserver') || 0; @@ -1464,6 +1466,31 @@ sub get_session { return $session; } +# Using Bcrypt method for hashing. This can be changed to something else in future, if needed. +sub hash_password { + my $password = shift; + + # Generate a salt if one is not passed + my $settings = shift; + unless( defined $settings ){ # if there are no settings, we need to create a salt and append settings + # Set the cost to 8 and append a NULL + $settings = '$2a$08$'.en_base64(generate_salt('strong')); + } + # Encrypt it + return bcrypt($password, $settings); +} + +# Return a random salt +sub generate_salt { + my ($type) = @_; + + if ($type eq 'strong') { + return Crypt::Random::Source::get_strong(16); + } else { + return Crypt::Random::Source::get_weak(16); + } +} + sub checkpw { my ( $dbh, $userid, $password, $query ) = @_; @@ -1489,10 +1516,18 @@ sub checkpw { ); $sth->execute($userid); if ( $sth->rows ) { - my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname, + my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname, $surname, $branchcode, $flags ) = $sth->fetchrow; - if ( md5_base64($password) eq $md5password and $md5password ne "!") { + + # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 + my $hash; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($password, $stored_hash); + } else { + $hash = md5_base64($password); + } + if ( $hash eq $stored_hash and $stored_hash ne "!") { C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); @@ -1505,10 +1540,19 @@ sub checkpw { ); $sth->execute($userid); if ( $sth->rows ) { - my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname, + my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname, $surname, $branchcode, $flags ) = $sth->fetchrow; - if ( md5_base64($password) eq $md5password ) { + + # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 + my $hash; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($password, $stored_hash); + } else { + $hash = md5_base64($password); + } + + if ( $hash eq $stored_hash ) { C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); diff --git a/C4/Members.pm b/C4/Members.pm index 7ac69df..f58bb76 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -24,7 +24,6 @@ use strict; #use warnings; FIXME - Bug 2505 use C4::Context; use C4::Dates qw(format_date_in_iso format_date); -use Digest::MD5 qw(md5_base64); use String::Random qw( random_string ); use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/; use C4::Log; # logaction @@ -40,6 +39,7 @@ use DateTime; use DateTime::Format::DateParse; use Koha::DateUtils; use Text::Unaccent qw( unac_string ); +use C4::Auth qw(hash_password); our ($VERSION, at ISA, at EXPORT, at EXPORT_OK,$debug); @@ -250,7 +250,7 @@ sub Search { $filter = [ $filter ]; push @$filter, {"borrowernumber"=>$matching_records}; } - } + } } # $showallbranches was not used at the time SearchMember() was mainstreamed into Search(). @@ -283,7 +283,7 @@ sub Search { } $searchtype ||= "start_with"; - return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype ); + return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype ); } =head2 GetMemberDetails @@ -750,11 +750,11 @@ sub ModMember { if ($data{password} eq '****' or $data{password} eq '') { delete $data{password}; } else { - $data{password} = md5_base64($data{password}); + $data{password} = hash_password($data{password}); } } my $old_categorycode = GetBorrowerCategorycode( $data{borrowernumber} ); - my $execute_success=UpdateInTable("borrowers",\%data); + my $execute_success=UpdateInTable("borrowers",\%data); if ($execute_success) { # only proceed if the update was a success # ok if its an adult (type) it may have borrowers that depend on it as a guarantor # so when we update information for an adult we should check for guarantees and update the relevant part @@ -805,10 +805,9 @@ sub AddMember { } # create a disabled account if no password provided - $data{'password'} = ($data{'password'})? md5_base64($data{'password'}) : '!'; + $data{'password'} = ($data{'password'})? hash_password($data{'password'}) : '!'; $data{'borrowernumber'}=InsertInTable("borrowers",\%data); - # mysql_insertid is probably bad. not necessarily accurate and mysql-specific at best. logaction("MEMBERS", "CREATE", $data{'borrowernumber'}, "") if C4::Context->preference("BorrowersLog"); @@ -1466,28 +1465,6 @@ sub GetExpiryDate { } } -=head2 checkuserpassword (OUEST-PROVENCE) - -check for the password and login are not used -return the number of record -0=> NOT USED 1=> USED - -=cut - -sub checkuserpassword { - my ( $borrowernumber, $userid, $password ) = @_; - $password = md5_base64($password); - my $dbh = C4::Context->dbh; - my $sth = - $dbh->prepare( -"Select count(*) from borrowers where borrowernumber !=? and userid =? and password=? " - ); - $sth->execute( $borrowernumber, $userid, $password ); - my $number_rows = $sth->fetchrow; - return $number_rows; - -} - =head2 GetborCatFromCatType ($codes_arrayref, $labels_hashref) = &GetborCatFromCatType(); diff --git a/members/member-password.pl b/members/member-password.pl index bed8fc4..d2a9a31 100755 --- a/members/member-password.pl +++ b/members/member-password.pl @@ -55,7 +55,7 @@ my $minpw = C4::Context->preference('minPasswordLength'); push(@errors,'SHORTPASSWORD') if( $newpassword && $minpw && (length($newpassword) < $minpw ) ); if ( $newpassword && !scalar(@errors) ) { - my $digest=md5_base64($input->param('newpassword')); + my $digest=C4::Auth::hash_password($input->param('newpassword')); my $uid = $input->param('newuserid'); my $dbh=C4::Context->dbh; if (changepassword($uid,$member,$digest)) { diff --git a/opac/opac-passwd.pl b/opac/opac-passwd.pl index 19425f7..923a5cf 100755 --- a/opac/opac-passwd.pl +++ b/opac/opac-passwd.pl @@ -29,6 +29,7 @@ use Digest::MD5 qw(md5_base64); use C4::Circulation; use C4::Members; use C4::Output; +use C4::Auth qw(hash_password); my $query = new CGI; my $dbh = C4::Context->dbh; @@ -57,7 +58,7 @@ if ( C4::Context->preference("OpacPasswordChange") ) { if ( $query->param('Newkey') eq $query->param('Confirm') && length( $query->param('Confirm') ) >= $minpasslen ) { # Record password - my $clave = md5_base64( $query->param('Newkey') ); + my $clave = hash_password( $query->param('Newkey') ); $sth->execute( $clave, $borrowernumber ); $template->param( 'password_updated' => '1' ); $template->param( 'borrowernumber' => $borrowernumber ); @@ -113,8 +114,14 @@ sub goodkey { $dbh->prepare("SELECT password FROM borrowers WHERE borrowernumber=?"); $sth->execute($borrowernumber); if ( $sth->rows ) { - my ($md5password) = $sth->fetchrow; - if ( md5_base64($key) eq $md5password ) { return 1; } + my $hash; + my ($stored_hash) = $sth->fetchrow; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($key, $stored_hash); + } else { + $hash = md5_base64($key); + } + if ( $hash eq $stored_hash ) { return 1; } else { return 0; } } else { return 0; } -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Aug 23 06:41:56 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 23 Aug 2013 16:41:56 +1200 Subject: [Koha-patches] [PATCH] bug 9611: removing external dependency for password salt generator Message-ID: <1377232916-24422-1-git-send-email-srdjan@catalyst.net.nz> From: Chris Hall To address packaging issues with Crypt::Random::Source, this patch replaces the salt generation with a wrapper for /dev/urandom and /dev/random. The test plan for this patch is the same as that for the base patch for bug 9611. Signed-off-by: Galen Charlton --- C4/Auth.pm | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/C4/Auth.pm b/C4/Auth.pm index 1e17e59..429181d 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -23,6 +23,8 @@ use Digest::MD5 qw(md5_base64); use JSON qw/encode_json decode_json/; use URI::Escape; use CGI::Session; +use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64); +use Fcntl qw/O_RDONLY/; # O_RDONLY is used in generate_salt require Exporter; use C4::Context; @@ -1464,6 +1466,91 @@ sub get_session { return $session; } +# Using Bcrypt method for hashing. This can be changed to something else in future, if needed. +sub hash_password { + my $password = shift; + + # Generate a salt if one is not passed + my $settings = shift; + unless( defined $settings ){ # if there are no settings, we need to create a salt and append settings + # Set the cost to 8 and append a NULL + $settings = '$2a$08$'.en_base64(generate_salt('weak', 16)); + } + # Encrypt it + return bcrypt($password, $settings); +} + +=head2 generate_salt + + use C4::Auth; + my $salt = C4::Auth::generate_salt($strength, $length); + +=item strength + +For general password salting a C<$strength> of C is recommend, +For generating a server-salt a C<$strength> of C is recommended + +'strong' uses /dev/random which may block until sufficient entropy is acheived. +'weak' uses /dev/urandom and is non-blocking. + +=back + +=item length + +C<$length> is a positive integer which specifies the desired length of the returned string + +=back + +=cut + + +# the implementation of generate_salt is loosely based on Crypt::Random::Provider::File +sub generate_salt { + # strength is 'strong' or 'weak' + # length is number of bytes to read, positive integer + my ($strength, $length) = @_; + + my $source; + + if( $length < 1 ){ + die "non-positive strength of '$strength' passed to C4::Auth::generate_salt\n"; + } + + if( $strength eq "strong" ){ + $source = '/dev/random'; # blocking + } else { + unless( $strength eq 'weak' ){ + warn "unsuppored strength of '$strength' passed to C4::Auth::generate_salt, defaulting to 'weak'\n"; + } + $source = '/dev/urandom'; # non-blocking + } + + sysopen SOURCE, $source, O_RDONLY + or die "failed to open source '$source' in C4::Auth::generate_salt\n"; + + # $bytes is the bytes just read + # $string is the concatenation of all the bytes read so far + my( $bytes, $string ) = ("", ""); + + # keep reading until we have $length bytes in $strength + while( length($string) < $length ){ + # return the number of bytes read, 0 (EOF), or -1 (ERROR) + my $return = sysread SOURCE, $bytes, $length - length($string); + + # if no bytes were read, keep reading (if using /dev/random it is possible there was insufficient entropy so this may block) + next unless $return; + if( $return == -1 ){ + die "error while reading from $source in C4::Auth::generate_salt\n"; + } + + $string .= $bytes; + } + + close SOURCE; + return $string; +} + + sub checkpw { my ( $dbh, $userid, $password, $query ) = @_; -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Aug 23 06:56:44 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 23 Aug 2013 16:56:44 +1200 Subject: [Koha-patches] [PATCH] Bug 9611: Change the password hashing algorithm from MD5 to Bcrypt Message-ID: <1377233804-27075-1-git-send-email-srdjan@catalyst.net.nz> From: Srikanth Dhondi What this patch aims to accomplish? * All new passwords are stored as Bcrypt-hashes * For password verification: - If the user was created before this patch was applied then use MD5 to hash the entered password <-- backwards compatibility - If the user was created after this patch was applied then use Bcrypt to hash the entered password * Any password change made via the staff interface or the OPAC will be automatically Bcrypt-hashed; this applies to old users whose passwords were stored as MD5 hashes previously Test plan: 1) Add new users and check whether their passwords are stored as Bcrypt hashes or not. 2) To test that authentication works for both old as well as new users: a) Login as an existing user whose password is stored as a MD5 hash b) Login as an existing user whose password is stored as a Bcrypt hash 3) In the staff interface, change the password of an existing user whose password is stored as an MD5 hash a) Check the new password is stored as a Bcrypt-hash in the database b) Try to login with the new password 4) In the OPAC, verify that a) Old user with old pass can change password, new format b) New user with new pass can change password c) Old and new user with self-updated pass can login Whitespace cleanup was contributed by Bernardo Gonzalez Kriegel. Signed-off-by: Bernardo Gonzalez Kriegel Signed-off-by: Mason James Signed-off-by: Galen Charlton --- C4/Auth.pm | 114 +++++++++++++++++++++++++++++++++++++++++++-- C4/Members.pm | 35 +++----------- members/member-password.pl | 2 +- opac/opac-passwd.pl | 13 ++++-- 4 files changed, 126 insertions(+), 38 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index 1e17e59..7674691 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -23,6 +23,8 @@ use Digest::MD5 qw(md5_base64); use JSON qw/encode_json decode_json/; use URI::Escape; use CGI::Session; +use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64); +use Fcntl qw/O_RDONLY/; # O_RDONLY is used in generate_salt require Exporter; use C4::Context; @@ -47,7 +49,7 @@ BEGIN { @ISA = qw(Exporter); @EXPORT = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions); @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &get_all_subpermissions &get_user_subpermissions - ParseSearchHistoryCookie + ParseSearchHistoryCookie hash_password ); %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] ); $ldap = C4::Context->config('useldapserver') || 0; @@ -1464,6 +1466,91 @@ sub get_session { return $session; } +# Using Bcrypt method for hashing. This can be changed to something else in future, if needed. +sub hash_password { + my $password = shift; + + # Generate a salt if one is not passed + my $settings = shift; + unless( defined $settings ){ # if there are no settings, we need to create a salt and append settings + # Set the cost to 8 and append a NULL + $settings = '$2a$08$'.en_base64(generate_salt('weak', 16)); + } + # Encrypt it + return bcrypt($password, $settings); +} + +=head2 generate_salt + + use C4::Auth; + my $salt = C4::Auth::generate_salt($strength, $length); + +=item strength + +For general password salting a C<$strength> of C is recommend, +For generating a server-salt a C<$strength> of C is recommended + +'strong' uses /dev/random which may block until sufficient entropy is acheived. +'weak' uses /dev/urandom and is non-blocking. + +=back + +=item length + +C<$length> is a positive integer which specifies the desired length of the returned string + +=back + +=cut + + +# the implementation of generate_salt is loosely based on Crypt::Random::Provider::File +sub generate_salt { + # strength is 'strong' or 'weak' + # length is number of bytes to read, positive integer + my ($strength, $length) = @_; + + my $source; + + if( $length < 1 ){ + die "non-positive strength of '$strength' passed to C4::Auth::generate_salt\n"; + } + + if( $strength eq "strong" ){ + $source = '/dev/random'; # blocking + } else { + unless( $strength eq 'weak' ){ + warn "unsuppored strength of '$strength' passed to C4::Auth::generate_salt, defaulting to 'weak'\n"; + } + $source = '/dev/urandom'; # non-blocking + } + + sysopen SOURCE, $source, O_RDONLY + or die "failed to open source '$source' in C4::Auth::generate_salt\n"; + + # $bytes is the bytes just read + # $string is the concatenation of all the bytes read so far + my( $bytes, $string ) = ("", ""); + + # keep reading until we have $length bytes in $strength + while( length($string) < $length ){ + # return the number of bytes read, 0 (EOF), or -1 (ERROR) + my $return = sysread SOURCE, $bytes, $length - length($string); + + # if no bytes were read, keep reading (if using /dev/random it is possible there was insufficient entropy so this may block) + next unless $return; + if( $return == -1 ){ + die "error while reading from $source in C4::Auth::generate_salt\n"; + } + + $string .= $bytes; + } + + close SOURCE; + return $string; +} + + sub checkpw { my ( $dbh, $userid, $password, $query ) = @_; @@ -1489,10 +1576,18 @@ sub checkpw { ); $sth->execute($userid); if ( $sth->rows ) { - my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname, + my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname, $surname, $branchcode, $flags ) = $sth->fetchrow; - if ( md5_base64($password) eq $md5password and $md5password ne "!") { + + # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 + my $hash; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($password, $stored_hash); + } else { + $hash = md5_base64($password); + } + if ( $hash eq $stored_hash and $stored_hash ne "!") { C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); @@ -1505,10 +1600,19 @@ sub checkpw { ); $sth->execute($userid); if ( $sth->rows ) { - my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname, + my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname, $surname, $branchcode, $flags ) = $sth->fetchrow; - if ( md5_base64($password) eq $md5password ) { + + # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 + my $hash; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($password, $stored_hash); + } else { + $hash = md5_base64($password); + } + + if ( $hash eq $stored_hash ) { C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); diff --git a/C4/Members.pm b/C4/Members.pm index 7ac69df..f58bb76 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -24,7 +24,6 @@ use strict; #use warnings; FIXME - Bug 2505 use C4::Context; use C4::Dates qw(format_date_in_iso format_date); -use Digest::MD5 qw(md5_base64); use String::Random qw( random_string ); use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/; use C4::Log; # logaction @@ -40,6 +39,7 @@ use DateTime; use DateTime::Format::DateParse; use Koha::DateUtils; use Text::Unaccent qw( unac_string ); +use C4::Auth qw(hash_password); our ($VERSION, at ISA, at EXPORT, at EXPORT_OK,$debug); @@ -250,7 +250,7 @@ sub Search { $filter = [ $filter ]; push @$filter, {"borrowernumber"=>$matching_records}; } - } + } } # $showallbranches was not used at the time SearchMember() was mainstreamed into Search(). @@ -283,7 +283,7 @@ sub Search { } $searchtype ||= "start_with"; - return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype ); + return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype ); } =head2 GetMemberDetails @@ -750,11 +750,11 @@ sub ModMember { if ($data{password} eq '****' or $data{password} eq '') { delete $data{password}; } else { - $data{password} = md5_base64($data{password}); + $data{password} = hash_password($data{password}); } } my $old_categorycode = GetBorrowerCategorycode( $data{borrowernumber} ); - my $execute_success=UpdateInTable("borrowers",\%data); + my $execute_success=UpdateInTable("borrowers",\%data); if ($execute_success) { # only proceed if the update was a success # ok if its an adult (type) it may have borrowers that depend on it as a guarantor # so when we update information for an adult we should check for guarantees and update the relevant part @@ -805,10 +805,9 @@ sub AddMember { } # create a disabled account if no password provided - $data{'password'} = ($data{'password'})? md5_base64($data{'password'}) : '!'; + $data{'password'} = ($data{'password'})? hash_password($data{'password'}) : '!'; $data{'borrowernumber'}=InsertInTable("borrowers",\%data); - # mysql_insertid is probably bad. not necessarily accurate and mysql-specific at best. logaction("MEMBERS", "CREATE", $data{'borrowernumber'}, "") if C4::Context->preference("BorrowersLog"); @@ -1466,28 +1465,6 @@ sub GetExpiryDate { } } -=head2 checkuserpassword (OUEST-PROVENCE) - -check for the password and login are not used -return the number of record -0=> NOT USED 1=> USED - -=cut - -sub checkuserpassword { - my ( $borrowernumber, $userid, $password ) = @_; - $password = md5_base64($password); - my $dbh = C4::Context->dbh; - my $sth = - $dbh->prepare( -"Select count(*) from borrowers where borrowernumber !=? and userid =? and password=? " - ); - $sth->execute( $borrowernumber, $userid, $password ); - my $number_rows = $sth->fetchrow; - return $number_rows; - -} - =head2 GetborCatFromCatType ($codes_arrayref, $labels_hashref) = &GetborCatFromCatType(); diff --git a/members/member-password.pl b/members/member-password.pl index bed8fc4..d2a9a31 100755 --- a/members/member-password.pl +++ b/members/member-password.pl @@ -55,7 +55,7 @@ my $minpw = C4::Context->preference('minPasswordLength'); push(@errors,'SHORTPASSWORD') if( $newpassword && $minpw && (length($newpassword) < $minpw ) ); if ( $newpassword && !scalar(@errors) ) { - my $digest=md5_base64($input->param('newpassword')); + my $digest=C4::Auth::hash_password($input->param('newpassword')); my $uid = $input->param('newuserid'); my $dbh=C4::Context->dbh; if (changepassword($uid,$member,$digest)) { diff --git a/opac/opac-passwd.pl b/opac/opac-passwd.pl index 19425f7..923a5cf 100755 --- a/opac/opac-passwd.pl +++ b/opac/opac-passwd.pl @@ -29,6 +29,7 @@ use Digest::MD5 qw(md5_base64); use C4::Circulation; use C4::Members; use C4::Output; +use C4::Auth qw(hash_password); my $query = new CGI; my $dbh = C4::Context->dbh; @@ -57,7 +58,7 @@ if ( C4::Context->preference("OpacPasswordChange") ) { if ( $query->param('Newkey') eq $query->param('Confirm') && length( $query->param('Confirm') ) >= $minpasslen ) { # Record password - my $clave = md5_base64( $query->param('Newkey') ); + my $clave = hash_password( $query->param('Newkey') ); $sth->execute( $clave, $borrowernumber ); $template->param( 'password_updated' => '1' ); $template->param( 'borrowernumber' => $borrowernumber ); @@ -113,8 +114,14 @@ sub goodkey { $dbh->prepare("SELECT password FROM borrowers WHERE borrowernumber=?"); $sth->execute($borrowernumber); if ( $sth->rows ) { - my ($md5password) = $sth->fetchrow; - if ( md5_base64($key) eq $md5password ) { return 1; } + my $hash; + my ($stored_hash) = $sth->fetchrow; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($key, $stored_hash); + } else { + $hash = md5_base64($key); + } + if ( $hash eq $stored_hash ) { return 1; } else { return 0; } } else { return 0; } -- 1.8.1.2 From srdjan at catalyst.net.nz Mon Aug 26 02:23:16 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Mon, 26 Aug 2013 12:23:16 +1200 Subject: [Koha-patches] [PATCH] bug_10781: Removed ILSDI::Utility Message-ID: <1377476596-24937-1-git-send-email-srdjan@catalyst.net.nz> Test: This should be a noop. Regression testing required: /cgi-bin/koha/ilsdi.pl functioanality, in particuler: GetAvailability - ?service=Describe&verb=GetAvailability AuthenticatePatron - ?service=Describe&verb=AuthenticatePatron ILS-DI syspref must be turned on --- C4/ILSDI/Services.pm | 40 ++++++++++++++++++- C4/ILSDI/Utility.pm | 107 --------------------------------------------------- t/ILSDI_Utility.t | 14 ------- 3 files changed, 38 insertions(+), 123 deletions(-) delete mode 100644 C4/ILSDI/Utility.pm delete mode 100755 t/ILSDI_Utility.t diff --git a/C4/ILSDI/Services.pm b/C4/ILSDI/Services.pm index dd43743..2eec0ac 100644 --- a/C4/ILSDI/Services.pm +++ b/C4/ILSDI/Services.pm @@ -29,11 +29,11 @@ use C4::Biblio; use C4::Reserves qw(AddReserve CancelReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber CanBookBeReserved CanItemBeReserved); use C4::Context; use C4::AuthoritiesMarc; -use C4::ILSDI::Utility; use XML::Simple; use HTML::Entities; use CGI; use DateTime; +use Data::Dumper; =head1 NAME @@ -114,7 +114,7 @@ sub GetAvailability { foreach my $id ( split( / /, $cgi->param('id') ) ) { if ( $cgi->param('id_type') eq "item" ) { - my ( $biblionumber, $status, $msg, $location ) = Availability($id); + my ( $biblionumber, $status, $msg, $location ) = _availability($id); $out .= " \n"; $out .= " \n"; @@ -767,4 +767,40 @@ sub CancelHold { return { code => 'Canceled' }; } +=head2 _availability + +Returns, for an itemnumber, an array containing availability information. + + my ($biblionumber, $status, $msg, $location) = _availability($id); + +=cut + +sub _availability { + my ($itemnumber) = @_; + my $item = GetItem( $itemnumber, undef, undef ); + + if ( not $item->{'itemnumber'} ) { + return ( undef, 'unknown', 'Error: could not retrieve availability for this ID', undef ); + } + + my $biblionumber = $item->{'biblioitemnumber'}; + my $location = GetBranchName( $item->{'holdingbranch'} ); + + if ( $item->{'notforloan'} ) { + return ( $biblionumber, 'not available', 'Not for loan', $location ); + } elsif ( $item->{'onloan'} ) { + return ( $biblionumber, 'not available', 'Checked out', $location ); + } elsif ( $item->{'itemlost'} ) { + return ( $biblionumber, 'not available', 'Item lost', $location ); + } elsif ( $item->{'wthdrawn'} ) { + return ( $biblionumber, 'not available', 'Item withdrawn', $location ); + } elsif ( $item->{'damaged'} ) { + return ( $biblionumber, 'not available', 'Item damaged', $location ); + } else { + return ( $biblionumber, 'available', undef, $location ); + } + + die Data::Dumper::Dumper($item); +} + 1; diff --git a/C4/ILSDI/Utility.pm b/C4/ILSDI/Utility.pm deleted file mode 100644 index b8c1457..0000000 --- a/C4/ILSDI/Utility.pm +++ /dev/null @@ -1,107 +0,0 @@ -package C4::ILSDI::Utility; - -# Copyright 2009 SARL Biblibre -# Copyright 2011 software.coop and MJ Ray -# -# This file is part of Koha. -# -# Koha is free software; you can redistribute it and/or modify it under the -# terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# Koha is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -# A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with Koha; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -use strict; -use warnings; - -use C4::Members; -use C4::Items; -use C4::Circulation; -use C4::Biblio; -use C4::Reserves qw(GetReservesFromBorrowernumber CanBookBeReserved); -use C4::Context; -use C4::Branch qw/GetBranchName/; -use Digest::MD5 qw(md5_base64); - -use vars qw($VERSION @ISA @EXPORT); - -BEGIN { - - # set the version for version checking - $VERSION = 3.07.00.049; - require Exporter; - @ISA = qw(Exporter); - @EXPORT = qw( - &BorrowerExists &Availability - ); -} - -=head1 NAME - -C4::ILS-DI::Utility - ILS-DI Utilities - -=cut - -=head2 BorrowerExists - -Checks, for a given userid and password, if the borrower exists. - - if ( BorrowerExists($userid, $password) ) { - # Do stuff - } - -=cut - -sub BorrowerExists { - my ( $userid, $password ) = @_; - $password = md5_base64($password); - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT COUNT(*) FROM borrowers WHERE userid =? and password=? "); - $sth->execute( $userid, $password ); - return $sth->fetchrow; -} - -=head2 Availability - -Returns, for an itemnumber, an array containing availability information. - - my ($biblionumber, $status, $msg, $location) = Availability($id); - -=cut - -sub Availability { - my ($itemnumber) = @_; - my $item = GetItem( $itemnumber, undef, undef ); - - if ( not $item->{'itemnumber'} ) { - return ( undef, 'unknown', 'Error: could not retrieve availability for this ID', undef ); - } - - my $biblionumber = $item->{'biblioitemnumber'}; - my $location = GetBranchName( $item->{'holdingbranch'} ); - - if ( $item->{'notforloan'} ) { - return ( $biblionumber, 'not available', 'Not for loan', $location ); - } elsif ( $item->{'onloan'} ) { - return ( $biblionumber, 'not available', 'Checked out', $location ); - } elsif ( $item->{'itemlost'} ) { - return ( $biblionumber, 'not available', 'Item lost', $location ); - } elsif ( $item->{'wthdrawn'} ) { - return ( $biblionumber, 'not available', 'Item withdrawn', $location ); - } elsif ( $item->{'damaged'} ) { - return ( $biblionumber, 'not available', 'Item damaged', $location ); - } else { - return ( $biblionumber, 'available', undef, $location ); - } - - die Data::Dumper::Dumper($item); -} - -1; diff --git a/t/ILSDI_Utility.t b/t/ILSDI_Utility.t deleted file mode 100755 index c06209b..0000000 --- a/t/ILSDI_Utility.t +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/perl -# -# This Koha test module is a stub! -# Add more tests here!!! - -use strict; -use warnings; - -use Test::More tests => 1; - -BEGIN { - use_ok('C4::ILSDI::Utility'); -} - -- 1.8.1.2 From srdjan at catalyst.net.nz Mon Aug 26 08:48:23 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Mon, 26 Aug 2013 18:48:23 +1200 Subject: [Koha-patches] [PATCH] bug_9611: Extracted checkpw_internal() and checkpw_hash() from checkpw() Message-ID: <1377499703-4846-1-git-send-email-srdjan@catalyst.net.nz> --- C4/Auth.pm | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index 7674691..829f26a 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -48,7 +48,8 @@ BEGIN { $debug = $ENV{DEBUG}; @ISA = qw(Exporter); @EXPORT = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions); - @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &get_all_subpermissions &get_user_subpermissions + @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &checkpw_internal &checkpw_hash + &get_all_subpermissions &get_user_subpermissions ParseSearchHistoryCookie hash_password ); %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] ); @@ -1552,8 +1553,8 @@ sub generate_salt { sub checkpw { - my ( $dbh, $userid, $password, $query ) = @_; + if ($ldap) { $debug and print STDERR "## checkpw - checking LDAP\n"; my ($retval,$retcard,$retuserid) = checkpw_ldap(@_); # EXTERNAL AUTH @@ -1563,13 +1564,18 @@ sub checkpw { if ($cas && $query && $query->param('ticket')) { $debug and print STDERR "## checkpw - checking CAS\n"; # In case of a CAS authentication, we use the ticket instead of the password - my $ticket = $query->param('ticket'); + my $ticket = $query->param('ticket'); my ($retval,$retcard,$retuserid) = checkpw_cas($dbh, $ticket, $query); # EXTERNAL AUTH ($retval) and return ($retval,$retcard,$retuserid); - return 0; + return 0; } - # INTERNAL AUTH + return checkpw_internal(@_) +} + +sub checkpw_internal { + my ( $dbh, $userid, $password ) = @_; + my $sth = $dbh->prepare( "select password,cardnumber,borrowernumber,userid,firstname,surname,branchcode,flags from borrowers where userid=?" @@ -1580,14 +1586,7 @@ sub checkpw { $surname, $branchcode, $flags ) = $sth->fetchrow; - # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 - my $hash; - if ( substr($stored_hash,0,2) eq '$2') { - $hash = hash_password($password, $stored_hash); - } else { - $hash = md5_base64($password); - } - if ( $hash eq $stored_hash and $stored_hash ne "!") { + if ( checkpw_hash($password, $stored_hash) ) { C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); @@ -1604,15 +1603,7 @@ sub checkpw { $surname, $branchcode, $flags ) = $sth->fetchrow; - # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 - my $hash; - if ( substr($stored_hash,0,2) eq '$2') { - $hash = hash_password($password, $stored_hash); - } else { - $hash = md5_base64($password); - } - - if ( $hash eq $stored_hash ) { + if ( checkpw_hash($password, $stored_hash) ) { C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); @@ -1639,6 +1630,21 @@ sub checkpw { return 0; } +sub checkpw_hash { + my ( $password, $stored_hash ) = @_; + + return if $stored_hash eq '!'; + + # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 + my $hash; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($password, $stored_hash); + } else { + $hash = md5_base64($password); + } + return $hash eq $stored_hash; +} + =head2 getuserflags my $authflags = getuserflags($flags, $userid, [$dbh]); -- 1.8.1.2 From srdjan at catalyst.net.nz Mon Aug 26 08:48:34 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Mon, 26 Aug 2013 18:48:34 +1200 Subject: [Koha-patches] [PATCH] bug_9611: removed md5_base64 from imports - not used Message-ID: <1377499714-4909-1-git-send-email-srdjan@catalyst.net.nz> --- C4/ImportExportFramework.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/C4/ImportExportFramework.pm b/C4/ImportExportFramework.pm index 72873f2..f85101d 100644 --- a/C4/ImportExportFramework.pm +++ b/C4/ImportExportFramework.pm @@ -21,7 +21,7 @@ use strict; use warnings; use XML::LibXML; use XML::LibXML::XPathContext; -use Digest::MD5 qw(md5_base64); +use Digest::MD5 qw(); use POSIX qw(strftime); use C4::Context; -- 1.8.1.2 From srdjan at catalyst.net.nz Mon Aug 26 08:48:46 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Mon, 26 Aug 2013 18:48:46 +1200 Subject: [Koha-patches] [PATCH] bug_9611: use checkpw_hash() instead of md5 hash Message-ID: <1377499726-4976-1-git-send-email-srdjan@catalyst.net.nz> Test: * SIP: Have an old user and create a new user - use either tenet sip test or C4/SIP/interactive_patron_check_password.pl to check old userid/password - do the same for the new user --- C4/SIP/ILS/Patron.pm | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/C4/SIP/ILS/Patron.pm b/C4/SIP/ILS/Patron.pm index ac24d2f..1a52944 100644 --- a/C4/SIP/ILS/Patron.pm +++ b/C4/SIP/ILS/Patron.pm @@ -21,7 +21,7 @@ use C4::Koha; use C4::Members; use C4::Reserves; use C4::Branch qw(GetBranchName); -use Digest::MD5 qw(md5_base64); +use C4::Auth qw(checkpw_hash); our $VERSION = 3.07.00.049; @@ -39,7 +39,7 @@ sub new { } $kp = GetMemberDetails($kp->{borrowernumber}); $debug and warn "new Patron (GetMemberDetails): " . Dumper($kp); - my $pw = $kp->{password}; ### FIXME - md5hash -- deal with . + my $pw = $kp->{password}; my $flags = $kp->{flags}; # or warn "Warning: No flags from patron object for '$patron_id'"; my $debarred = defined($kp->{flags}->{DBARRED}); $debug and warn sprintf("Debarred = %s : ", ($debarred||'undef')) . Dumper(%{$kp->{flags}}); @@ -189,11 +189,13 @@ sub AUTOLOAD { sub check_password { my ($self, $pwd) = @_; - my $md5pwd = $self->{password}; + defined $pwd or return 0; # you gotta give me something (at least ''), or no deal + + my $hashed_pwd = $self->{password}; + defined $hashed_pwd or return $pwd eq ''; # if the record has a NULL password, accept '' as match + # warn sprintf "check_password for %s: '%s' vs. '%s'",($self->{name}||''),($self->{password}||''),($pwd||''); - (defined $pwd ) or return 0; # you gotta give me something (at least ''), or no deal - (defined $md5pwd) or return($pwd eq ''); # if the record has a NULL password, accept '' as match - return (md5_base64($pwd) eq $md5pwd); + return checkpw_hash($pwd, $hashed_pwd); } # A few special cases, not in AUTOLOADed %fields -- 1.8.1.2 From srdjan at catalyst.net.nz Mon Aug 26 08:50:48 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Mon, 26 Aug 2013 18:50:48 +1200 Subject: [Koha-patches] [PATCH] bug_9611: use hash_password() and checkpw_* instead of md5 hash Message-ID: <1377499848-5253-1-git-send-email-srdjan@catalyst.net.nz> Test: * LDAP: - Turn on LDAP auth in koha-config.xml. Sset "update" in your server config to 1 - Change user's password on LDAP - Login to Koha using LDAP - Koha password should be updated, to check - Turn off LDAP auth in koha-config.xml - You should be ble to log in with the new password I do not have a LDAP facility, so I cheated. I ran perl -e 'use C4::Auth_with_ldap; C4::Auth_with_ldap::_do_changepassword("srdjan", 1000022259, "srdjan");' and was able to change the password. --- C4/Auth_with_ldap.pm | 64 ++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/C4/Auth_with_ldap.pm b/C4/Auth_with_ldap.pm index 6143c9f..49ffc70 100644 --- a/C4/Auth_with_ldap.pm +++ b/C4/Auth_with_ldap.pm @@ -19,7 +19,7 @@ package C4::Auth_with_ldap; use strict; #use warnings; FIXME - Bug 2505 -use Digest::MD5 qw(md5_base64); +use Carp; use C4::Debug; use C4::Context; @@ -27,6 +27,7 @@ use C4::Members qw(AddMember changepassword); use C4::Members::Attributes; use C4::Members::AttributeTypes; use C4::Utils qw( :all ); +use C4::Auth qw(hash_password checkpw_internal); use List::MoreUtils qw( any ); use Net::LDAP; use Net::LDAP::Filter; @@ -264,44 +265,43 @@ sub exists_local { } sub _do_changepassword { - my ($userid, $borrowerid, $digest) = @_; + my ($userid, $borrowerid, $password) = @_; + + my $digest = hash_password($password); + $debug and print STDERR "changing local password for borrowernumber=$borrowerid to '$digest'\n"; changepassword($userid, $borrowerid, $digest); - # Confirm changes - my $sth = C4::Context->dbh->prepare("SELECT password,cardnumber FROM borrowers WHERE borrowernumber=? "); - $sth->execute($borrowerid); - if ($sth->rows) { - my ($md5password, $cardnum) = $sth->fetchrow; - ($digest eq $md5password) and return $cardnum; - warn "Password mismatch after update to cardnumber=$cardnum (borrowernumber=$borrowerid)"; - return; - } - die "Unexpected error after password update to userid/borrowernumber: $userid / $borrowerid."; + my ($ok, $cardnum) = checkpw_internal(C4::Context->dbh, $userid, $password); + return $cardnum if $ok; + + warn "Password mismatch after update to borrowernumber=$borrowerid"; + return; } sub update_local { - my $userid = shift or return; - my $digest = md5_base64(shift) or return; - my $borrowerid = shift or return; - my $borrower = shift or return; - my @keys = keys %$borrower; - my $dbh = C4::Context->dbh; - my $query = "UPDATE borrowers\nSET " . - join(',', map {"$_=?"} @keys) . - "\nWHERE borrowernumber=? "; - my $sth = $dbh->prepare($query); - if ($debug) { - print STDERR $query, "\n", - join "\n", map {"$_ = '" . $borrower->{$_} . "'"} @keys; - print STDERR "\nuserid = $userid\n"; - } - $sth->execute( - ((map {$borrower->{$_}} @keys), $borrowerid) - ); + my $userid = shift or croak "No userid"; + my $password = shift or croak "No password"; + my $borrowerid = shift or croak "No borrowerid"; + my $borrower = shift or croak "No borrower record"; + + my @keys = keys %$borrower; + my $dbh = C4::Context->dbh; + my $query = "UPDATE borrowers\nSET " . + join(',', map {"$_=?"} @keys) . + "\nWHERE borrowernumber=? "; + my $sth = $dbh->prepare($query); + if ($debug) { + print STDERR $query, "\n", + join "\n", map {"$_ = '" . $borrower->{$_} . "'"} @keys; + print STDERR "\nuserid = $userid\n"; + } + $sth->execute( + ((map {$borrower->{$_}} @keys), $borrowerid) + ); - # MODIFY PASSWORD/LOGIN - _do_changepassword($userid, $borrowerid, $digest); + # MODIFY PASSWORD/LOGIN + _do_changepassword($userid, $borrowerid, $password); } 1; -- 1.8.1.2 From tomascohen at gmail.com Thu Aug 29 20:09:52 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Thu, 29 Aug 2013 15:09:52 -0300 Subject: [Koha-patches] [PATCH] Bug 10802: Packages should install history.txt Message-ID: <1377799792-4659-1-git-send-email-tomascohen@gmail.com> While bug 8911 fixed a problem regarding history.txt, a proper fix for packages was missing. This patch does three things: - Adds docs/history.txt to debian/koha-common.docs so it gets installed. - Moves the line installing the release notes from debian/koha-common.install to debian/koha-common.docs. - Adds an override_dh_compress entry in debian/rules that excludes history.txt from the dh_compress routine [1] To test: - Take a picture of how /usr/share/doc/koha-common looks. - Apply the patch and build a package [2]. - Upgrade and/or install using your package. - Look for the contents of the /usr/share/doc/koha-common, it should look the same, but history.txt must be there. - More > About Koha > Koha Timeline should show the history lines. Regards To+ [1] As 'man dh_compress' says, it is needed as every file considered for the doc dir that is plain text and is more than 4k size will be gzipped unless stated otherwise. We need it uncompressed for about.pl. [2] I did it for you, it can be grabbed here: http://ubuntu.unc.edu.ar/koha/koha-common_3.13-1~git+20130829144510.18a6876b_all.deb Sponsored-by: Universidad Nacional de Cordoba --- debian/koha-common.docs | 2 ++ debian/koha-common.install | 1 - debian/rules | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/debian/koha-common.docs b/debian/koha-common.docs index 06575bd..6106c24 100644 --- a/debian/koha-common.docs +++ b/debian/koha-common.docs @@ -1 +1,3 @@ debian/docs/LEEME.Debian +misc/release_notes/release_notes_3*.txt +docs/history.txt diff --git a/debian/koha-common.install b/debian/koha-common.install index 810aadc..e215bde 100644 --- a/debian/koha-common.install +++ b/debian/koha-common.install @@ -1,4 +1,3 @@ -misc/release_notes/release_notes_3*.txt usr/share/doc/koha-common debian/tmp/usr/* usr debian/tmp/etc/koha/searchengine debian/tmp/etc/koha/pazpar2 diff --git a/debian/rules b/debian/rules index cbcfaaf..2073ad2 100755 --- a/debian/rules +++ b/debian/rules @@ -103,3 +103,7 @@ override_dh_auto_install: xsltproc --output $(TMP)/debian/tmp_docbook/ \ /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl \ debian/docs/*.xml + +override_dh_compress: + # exclude history.txt from compression as about.pl needs it uncompressed + dh_compress --exclude=history.txt -- 1.7.9.5 From tomascohen at gmail.com Fri Aug 30 16:45:22 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Fri, 30 Aug 2013 11:45:22 -0300 Subject: [Koha-patches] [PATCH] Bug 10003: bash-completion for koha-list and some other script Message-ID: <1377873922-5308-1-git-send-email-tomascohen@gmail.com> This is an initial commit submitted for peer review. It implements bash-completion for the following commands: - koha-list - koha-enable - koha-disable - koha-email-enable - koha-email-disable - koha-enable-sip - koha-start-sip - koha-restart-sip - koha-stop-sip - koha-start-zebra - koha-stop-zebra - koha-restart-zebra It is implemented in a way that it removes already used or mutually exclusive parameters (instance names, option switches). I already have written completion for other (more complex) commands, But I belive a simpler patch is better to start with. IMPORTANT: this patch relies on having the koha-list command available in the path. Also 10622 is needed for the SIP-related option switches. To test: - Make sure you have bash-completion installed and enabled (IRC might help us if you encounter problems). - Apply the patch. Option 1: - Pick the debian/koha-common.bash-completion file and do $ cp debian/koha-common.bash-completion /etc/bash_completion.d/koha-common - Open a new bash shell (I do it opening a new terminal on my Ubuntu box). - Type one of the listed commands... And repeatedly press . - Enjoy, and signoff if you belive it is usable. Otherwise report back. Option 2: - run: $ . debian/koha-common.bash-completion - Type one of the listed commands... And repeatedly press . - Enjoy, and signoff if you belive it is usable. Otherwise report back. Tests: - Some koha-list option switches are mutually exclusive, -h should be available in any context - koha-enable should only autocomplete disabled instances - koha-disable should only autocomplete enabled instances - koha-email-enable should only autocomplete email-disabled instances - koha-email-disable should only autocomplete email-enabled instances - koha-*-zebra scripts should only autocomplete enabled instances. - koha-*-sip scripts should only autocomplete sip-enabled instances. Regards To+ Note: writing bash-completion routines is a bit hacky, I tried to make it the simplest way I could. Your comments are welcome. Sponsored-by: Universidad Nacional de Cordoba --- debian/koha-common.bash-completion | 160 ++++++++++++++++++++++++++++++++++++ debian/rules | 2 +- 2 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 debian/koha-common.bash-completion diff --git a/debian/koha-common.bash-completion b/debian/koha-common.bash-completion new file mode 100644 index 0000000..cfaaffb --- /dev/null +++ b/debian/koha-common.bash-completion @@ -0,0 +1,160 @@ +#!/bin/bash +# +# koha-common.bash-completion script for koha-* commands +# +# This file is part of Koha. +# +# Copyright 2013 Universidad Nacional de Cordoba +# Tomas Cohen Arazi +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, see . + +_build_substract_switches() +{ + local substract + + for (( i=0; i < ${#COMP_WORDS[@]}-1; i++ )); do + if [[ ${COMP_WORDS[i]} == -* ]]; then + substract="$substract -e ${COMP_WORDS[i]}" + fi + done + + echo "$substract" +} + +_koha_list_cmd() +{ + local filter=$1 + + local cur substract instancelist + _get_comp_words_by_ref cur + + # Build a list of the already used words + substract=`_build_substract_switches` + + if [[ "$substract" != "" ]]; then + instancelist=$( koha-list $filter | grep -v -x $substract ) + else + instancelist=$( koha-list $filer ) + fi + + COMPREPLY=( $(compgen -W "$instancelist" -- $cur ) ) +} + +_koha_email_disable() +{ + _koha_list_cmd "--email" + return 0 +} +complete -F _koha_email_disable koha-email-disable + +_koha_email_enable() +{ + _koha_list_cmd "--noemail" + return 0 +} +complete -F _koha_email_enable koha-email-enable + +_koha_sip_enabled_instances() +{ + _koha_list_cmd "--sip" + return 0 +} + +# koha-*-sip autocomplete with sip-enabled instances +complete -F _koha_sip_enabled_instances koha-start-sip +complete -F _koha_sip_enabled_instances koha-restart-sip +complete -F _koha_sip_enabled_instances koha-stop-sip + +_koha_sip_disabled() +{ + _koha_list_cmd "--nosip" + return 0 +} + +# koha-enable-sip autocompletes with sip-disabled instances +complete -F _koha_sip_disabled koha-enable-sip + +_koha_disabled_instances() +{ + _koha_list_cmd "--disabled" + return 0 +} + +_koha_enabled_instances() +{ + _koha_list_cmd "--enabled" + return 0 +} + +# koha-enable autocompletes with disabled instances +complete -F _koha_disabled_instances koha-enable + +# koha-disable autocompletes with enabled instances +complete -F _koha_enabled_instances koha-disable + +# koha-*-zebra autocomplete with enabled instances +complete -F _koha_enabled_instances koha-start-zebra +complete -F _koha_enabled_instances koha-restart-zebra +complete -F _koha_enabled_instances koha-stop-zebra + +_koha_list() +{ + local cur opts substract + + COMPREPLY=() + _get_comp_words_by_ref cur + opts="--enabled --disabled --email --noemail --sip --nosip --help -h" + + # Build a list of the already used option switches + for (( i=0; i < ${#COMP_WORDS[@]}-1; i++ )); do + if [[ ${COMP_WORDS[i]} == -* ]]; then + case ${COMP_WORDS[i]} in + --disabled) + substract="$substract -e --enabled"; ;; + --enabled) + substract="$substract -e --disabled"; ;; + --email) + substract="$substract -e --noemail"; ;; + --noemail) + substract="$substract -e --email"; ;; + --sip) + substract="$substract -e --nosip"; ;; + --nosip) + substract="$substract -e --sip"; ;; + --help) + substract="$substract -e -h"; ;; + -h) + substract="$substract -e --help"; ;; + esac + substract="$substract -e ${COMP_WORDS[i]}" + fi + done + + if [[ "$substract" != "" ]]; then + opts=$( echo $opts | sed -e 's/ /\n/g' | grep -v -x $substract ) + fi + + COMPREPLY=( $(compgen -W "$opts" -- $cur ) ) + + return 0 +} +complete -F _koha_list koha-list + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/debian/rules b/debian/rules index cbcfaaf..ed1d34d 100755 --- a/debian/rules +++ b/debian/rules @@ -6,7 +6,7 @@ TMP = $(CURDIR)/debian/tmp export PERL_MM_USE_DEFAULT=1 %: - dh $@ --fail-missing + dh $@ --fail-missing --with bash-completion override_dh_gencontrol: debian/bd-to-depends >> debian/koha-common.substvars -- 1.7.9.5 From tomascohen at gmail.com Fri Aug 30 18:26:08 2013 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Fri, 30 Aug 2013 13:26:08 -0300 Subject: [Koha-patches] [PATCH] Bug 10624: 'status' option switch for the packages init script Message-ID: <1377879968-16656-1-git-send-email-tomascohen@gmail.com> This patch makes the init script return the status of the relevant processes. It relies on the koha-list switches added by 10622, and is written on top of the patch from 10617 that cleaned the init script. To test: - Apply the patch (+ 10622 so the SIP part works), build package and install - Run $ service koha-common status Note: it can be tested just copying the debian/koha-common.init script to a server running koha-common instances and calling it $ ./koha-common.init status If you don't have a patched koha-list command it will fail to report SIP servers status. Regards To+ Sponsored-by: Universidad Nacional de Cordoba --- debian/koha-common.init | 79 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/debian/koha-common.init b/debian/koha-common.init index 2899343..4c730a9 100755 --- a/debian/koha-common.init +++ b/debian/koha-common.init @@ -70,6 +70,74 @@ do_reload() { koha-start-sip $(koha-list --enabled) } +# +# Function that checks zebrasrv is running for the specified instance +# +is_zebra_running() +{ + local instancename=$1 + + if daemon --name="$instancename-koha-zebra" \ + --user="$instancename-koha.$instancename-koha" \ + --running ; then + return 0 + else + return 1 + fi +} + +# +# Function that checks SIP server is running for the specified instance +# +is_sip_running() +{ + local instancename=$1 + + if daemon --name="$instancename-koha-sip" \ + --user="$instancename-koha.$instancename-koha" \ + --running ; then + return 0 + else + return 1 + fi +} + +# +# Function that shows the status of the zebrasrv daemon for +# enabled instances +# +zebra_status() +{ + for instance in $(koha-list --enabled); do + + log_daemon_msg "Zebra server running for instace $instance" + + if is_zebra_running $instance ; then + log_end_msg 0 + else + log_end_msg 1 + fi + done +} + +# +# Function that shows the status of the SIP server daemon for +# enabled instances +# +sip_status() +{ + for instance in $(koha-list --enabled --sip); do + + log_daemon_msg "SIP server running for instace $instance" + + if is_sip_running $instance ; then + log_end_msg 0 + else + log_end_msg 1 + fi + done +} + case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" @@ -108,13 +176,12 @@ case "$1" in ;; esac ;; -# TODO: Implement this. It should check every daemon is running -# status) -# status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? -# ;; + status) + zebra_status + sip_status + ;; *) - #echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2 - echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2 exit 3 ;; esac -- 1.7.9.5