Changeset 31537
- Timestamp:
- 2017-03-24T21:37:12+13:00 (7 years ago)
- Location:
- main/trunk/greenstone3
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Construct.java
r31127 r31537 29 29 import java.util.Map; 30 30 import java.util.Set; 31 import java.util.regex.Matcher; 32 import java.util.regex.Pattern; 31 33 32 34 import org.apache.log4j.Logger; … … 42 44 import org.greenstone.gsdl3.util.UserContext; 43 45 import org.greenstone.gsdl3.util.XMLConverter; 46 47 // https://developer.android.com/reference/org/json/JSONObject.html 48 // https://developer.android.com/reference/org/json/JSONArray.html 49 import org.json.JSONArray; 50 import org.json.JSONException; 51 import org.json.JSONObject; 52 44 53 45 54 import org.w3c.dom.Document; … … 311 320 protected Element processModifyMetadata(Element request) 312 321 { 313 if (!userHasCollectionEditPermissions(request)) { 322 323 // There are two types of operations whereby metadata gets modified: 324 // - document including document-meta editing: user needs document editing powers 325 // - adding user comments: user just needs an account and needs to be logged in 326 // We handle both cases in this service. 327 328 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); 329 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false); 330 331 // If a user is only adding comments, they don't need to have editing powers over a collection 332 // but they need to be logged in 333 String[] docids = isAddingUserComments(request, params); 334 boolean isAddingUserComments = (docids == null) ? false : true; 335 336 if(isAddingUserComments) { // adding user comments, check if user logged in 337 UserContext context = new UserContext(request); 338 339 // A restricted set of metadata is modifiable when adding user comments: 340 // only the username, usertimestamp and usercomment metadata fields. 341 // If that's all that's being modified, isAddingUserComments() would have returned true, 342 // so finally check if the caller is logged in as a user. 343 if (context.getUsername().equals("")) { 344 Document result_doc = XMLConverter.newDOM(); 345 Element result = GSXML.createBasicResponse(result_doc, "processModifyMetadata"); 346 GSXML.addError(result, "Cannot add user comments if not logged in."); // or if attempting to set meta not related to user comments. 347 return result; // not logged in 348 } 349 350 } 351 else if (!userHasCollectionEditPermissions(request, params)) { 314 352 Document result_doc = XMLConverter.newDOM(); 315 353 Element result = GSXML.createBasicResponse(result_doc, "processModifyMetadata"); 316 GSXML.addError(result, "This user does not have the required permissions to perform this action."); 354 GSXML.addError(result, "This user does not have the required permissions to perform this action."); // also get here if user was attempting to set meta not related to user comments. 317 355 return result; 318 356 } … … 323 361 324 362 // process 325 Element response = runCommand(request, GS2PerlConstructor.MODIFY_METADATA_SERVER );363 Element response = runCommand(request, GS2PerlConstructor.MODIFY_METADATA_SERVER, docids); 326 364 327 365 if (response.getElementsByTagName(GSXML.ERROR_ELEM).getLength() <= 0) // if no errors, wait for process to finish … … 666 704 } 667 705 706 protected Element runCommand(Element request, int type) { 707 return runCommand(request, type, null); 708 } 709 668 710 /** returns a response element */ 669 protected Element runCommand(Element request, int type )670 { 671 711 protected Element runCommand(Element request, int type, String[] docids) 712 { 713 Document result_doc = XMLConverter.newDOM(); 672 714 // the response to send back 673 715 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT)); … … 757 799 758 800 String oid = null; 759 801 760 802 while (i.hasNext()) { 761 803 762 804 Map.Entry<String, Serializable> entry = i.next(); 763 805 String paramname = entry.getKey(); 764 paramname = paramname.replace("s1.", ""); // replaces all 765 // occurrences 806 paramname = paramname.replace("s1.", ""); // replaces all occurrences 766 807 if (paramname.equals("collection")) { 767 808 paramname = "c"; … … 770 811 oid = (String) entry.getValue(); 771 812 } 813 772 814 String paramvalue = (String) entry.getValue(); 773 815 … … 778 820 } 779 821 780 markDocumentInFlatDatabase("R", coll_name, OID.getTop(oid)); 822 if(oid != null) { // if we have only one oid 823 markDocumentInFlatDatabase("R", coll_name, OID.getTop(oid)); 824 } else if (docids != null) { // check if we are dealing with many doc ids, as cold in theory happen when set-metadata-array is called 825 826 for(int index = 0; index < docids.length; index++) { 827 String docid = docids[index]; 828 markDocumentInFlatDatabase("R", coll_name, OID.getTop(docid)); 829 } 830 } else { 831 String msg = getTextString("general.no_valid_docid_error", lang); 832 logger.error("*** " + msg); 833 Text t = result_doc.createTextNode(msg); 834 status.appendChild(t); 835 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR)); 836 return response; 837 } 781 838 782 839 constructor.setQueryString(querystring.toString()); … … 965 1022 966 1023 1024 protected String[] isAddingUserComments(Element request, HashMap<String, Serializable> params) { 1025 1026 String metaserver_command = (String) params.get("a"); // e.g. set-archives-metadata or set-metadata-array 1027 // quickest test: 1028 // if not calling set-metadata-array, then it definitely won't be a set-usercomments operation 1029 if(!metaserver_command.equals("set-metadata-array")) { 1030 return null; 1031 } 1032 1033 // Confirm that the set-meta-array operation is only attempting to modify user comments metadata 1034 1035 String[] docids = null; 1036 String json_str = (String) params.get("json"); // will have a "json" field if doing set-meta-array 1037 Pattern p = Pattern.compile("^(username|usertimestamp|usercomment)$"); 1038 1039 // check that the name of each that's metadata to be set is one of username|usercomment|usertimestamp 1040 // Anything else means something more than adding user comments is being attempted, which is invalid 1041 try { 1042 1043 JSONArray docInfoList = new JSONArray(json_str); 1044 docids = new String[docInfoList.length()]; 1045 for(int index = 0; index < docInfoList.length(); index++) { 1046 JSONObject docInfo = docInfoList.getJSONObject(index); 1047 if(docInfo.has("metatable")) { // should exist for metadata arrays 1048 1049 docids[index] = docInfo.getString("docid"); // should exist if metatable existed 1050 1051 logger.info("@@@ Found docid: " + docids[index]); 1052 1053 JSONArray metatable = docInfo.getJSONArray("metatable"); 1054 for(int i = 0; i < metatable.length(); i++) { 1055 JSONObject meta = metatable.getJSONObject(i); 1056 1057 String metaname = meta.getString("metaname"); 1058 logger.info("### metaname: " + metaname); 1059 Matcher m = p.matcher(metaname); 1060 if(!m.matches()) { 1061 logger.info("### metaname: " + metaname + " doesn't match"); 1062 return null; 1063 } 1064 } 1065 } 1066 } 1067 } catch(JSONException jsonex) { 1068 logger.error("Exception when parsing json string: " + json_str); 1069 logger.error(jsonex); 1070 1071 } 1072 1073 // if we're here, then it means that the JSON only asked for username|usercomment|usertimestamp meta 1074 // meaning that the setmeta operation was a valid user comment operation. 1075 // In that case, we have a docid for which we need to add a user comment 1076 // set-metadata-array can take more docids, but doesn't happen for a user comment. And one comment 1077 // is added at a time, but 3 meta fields are set for each comment: username, usercomment and timestamp 1078 // hence the use of set-meta-array. 1079 return docids; 1080 1081 } 1082 967 1083 /** Copy from DebugService.userHasEditPermissions 968 1084 This function checks that the user is logged in and that the user … … 971 1087 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); 972 1088 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false); 1089 1090 return userHasCollectionEditPermissions(request, params); 1091 1092 } 1093 1094 protected boolean userHasCollectionEditPermissions(Element request, HashMap<String, Serializable> params) { 973 1095 String collection = (String) params.get(COL_PARAM); // could be null on newcoll operation 1096 974 1097 975 1098 UserContext context = new UserContext(request); … … 977 1100 return !context.getUsername().equals(""); 978 1101 } 1102 1103 // START DEBUG 1104 Set<Map.Entry<String, Serializable>> entries = params.entrySet(); 1105 Iterator<Map.Entry<String, Serializable>> i = entries.iterator(); 1106 1107 StringBuffer parametersLine = new StringBuffer(); 1108 while (i.hasNext()) { 1109 1110 Map.Entry<String, Serializable> entry = i.next(); 1111 String paramname = entry.getKey(); 1112 String paramvalue = (String) entry.getValue(); 1113 1114 parametersLine.append("\t" + paramname + ": " + paramvalue + "\n"); 1115 } 1116 1117 logger.info("XXXXXXXXXXXXX PARAMETERS:\n" + parametersLine); 1118 // END DEBUG 1119 979 1120 for (String group : context.getGroups()) { 980 1121 // administrator always has permission -
main/trunk/greenstone3/web/WEB-INF/classes/GS2Construct.properties
r10042 r31537 59 59 general.configure_constructor_error=Couldn't configure the collection constructor. 60 60 general.process_start=Starting process... 61 general.no_valid_docid_error=Both oid and docids are null. Could happen if adding user comments attempted to set non-usercomment meta. 61 62 62 63 … … 65 66 66 67 67 -
main/trunk/greenstone3/web/WEB-INF/classes/interface_default.properties
r31381 r31537 141 141 142 142 doc.map_nearby_docs=Show documents near here 143 143 144 maps.scrolllabel=Scroll through places 144 145 … … 146 147 external.text=The link you have selected is external to any of your currently selected collections. If you still wish to view this link and your browser has access to the Web, you can {0-go-forward-link} to this page; otherwise use your browsers 'back' button to return to the previous document. 147 148 external.go_forward=go forward 149 150 ######################################################### 151 # User Comments section (available on a document page) # 152 ######################################################### 153 154 usercomments.username=User name 155 usercomments.add=Add Comment 156 usercomments.submit=Submit Comment 157 usercomments.submitted=Comment Submitted 158 usercomments.isempty=Comment was empty. 159 usercomments.heading=Comments 148 160 149 161 ##################### -
main/trunk/greenstone3/web/interfaces/default/js/javascript-global-functions.js
r31529 r31537 422 422 } 423 423 424 function callMetadataServer(callingFunction, url, responseFunction) 424 // No function overloading in JavaScript. Can pass a custom object, however, see 425 // http://stackoverflow.com/questions/456177/function-overloading-in-javascript-best-practices 426 function callMetadataServer(callingFunction, url, responseFunction, opts) 425 427 { 426 428 var async_setting = true; // Internal processing of 'read' operations (get meta) is not order dependent … … 445 447 } // otherwise, such as for get- metadata operation, we proceed as before, which will not require authentication 446 448 449 if (opts != null && opts["forceSync"] != null) { 450 async_setting = (!opts["forceSync"]); 451 } 452 453 console.log("Away to call: " + url); 454 var ajaxResponse = null; 447 455 448 456 $.ajax(url, {async: async_setting}) … … 451 459 console.log("(" + callingFunction + ") Response received from server: " + response); 452 460 461 ajaxResponse = response; 462 453 463 //var xml = $.parseXML(response); 454 464 //console.log(xml); … … 456 466 if(responseFunction != null) 457 467 { 458 responseFunction(response); 468 469 responseFunction(response); 459 470 } 460 471 }) … … 463 474 console.log("(" + callingFunction + ") Failed"); 464 475 }); 476 477 console.log("Finished ajax call to: " + url); 478 479 console.log("Got response: " + ajaxResponse); 480 return ajaxResponse; 465 481 } 466 482 … … 513 529 } 514 530 531 // New. Modified version of the GS2 version of this method in gsajaxapi.js. 532 // The where parameter can be specified as one or more of: import, archives, index, live 533 // separated by |. If null, it is assumed to be index which is the original default 534 // behaviour of calling set-metadata-array. E.g. where=import|archives|index 535 // THIS METHOD IS SYNCHRONOUS 536 gs.functions.setMetadataArray = function(collection, site, docArray, metamode, where, responseFunction) 537 { 538 docArrayJSON = JSON.stringify(docArray); 539 540 var params = "a=" + escape("set-metadata-array"); //"a=set-metadata-array"; 541 if(where != null) { 542 params += "&where=" + escape(where); // if where not specified, meta-server will default to setting index meta 543 //} else { 544 // params += "&where=import|archives|index"; 545 } 546 params += "&c="+escape(collection); 547 params += "&site="+escape(site); 548 params += "&json="+escape(docArrayJSON); 549 550 if (metamode!=null) { 551 params += "&metamode=" + escape(metamode); 552 } 553 554 555 var response = callMetadataServer("Setting metadata in "+where, "cgi-bin/metadata-server.pl?"+params, responseFunction); 556 557 return response; 558 // return this.urlPostSync(mdserver,params); // gsajaxapi.js version for GS2 559 } 560 561 515 562 /************************* 516 563 * GET METADATA FUNCTIONS * 517 564 *************************/ 518 565 566 // New. Modified version of the GS2 version of this method in gsajaxapi.js. 567 // See description for setMetadataArray above for information about the 'where' parameter. 568 // THIS METHOD IS SYNCHRONOUS BY DEFAULT. Set forceSync to false to override this default behaviour 569 gs.functions.getMetadataArray = function(collection, site, docArray, where, forceSync, responseFunction) 570 { 571 docArrayJSON = JSON.stringify(docArray); 572 573 var params = "a=" + escape("get-metadata-array"); //"a=set-metadata-array"; 574 if(where != null) { 575 params += "&where=" + escape(where); // if where not specified, meta-server will default to setting index meta 576 //} else { 577 // params += "&where=import|archives|index"; 578 } 579 params += "&c="+escape(collection); 580 params += "&site="+escape(site); 581 params += "&json="+escape(docArrayJSON); 582 583 // get operations are generally asynchronous, but allow calling function to force ajax call 584 // to be synchronous or not. Default is synchronous, as it was for GS2 585 if(forceSync == null) { 586 forceSync = true; 587 } 588 // Objects/maps can use identifiers or strings for property names 589 // http://stackoverflow.com/questions/456177/function-overloading-in-javascript-best-practices 590 // https://www.w3schools.com/js/js_objects.asp 591 var response = callMetadataServer("Getting metadata from "+where, "cgi-bin/metadata-server.pl?"+params, responseFunction, {"forceSync":forceSync}); 592 593 return response; 594 //return this.urlPostSync(mdserver,params); // gsajaxapi.js version for GS2 595 } 596 597 519 598 gs.functions.getImportMetadata = function(collection, site, documentID, metadataName, responseFunction) 520 599 { -
main/trunk/greenstone3/web/interfaces/default/style/core.css
r31530 r31537 1240 1240 } 1241 1241 1242 /* User comments area: display of existing user comments and display of the form and of the add user/logout links */ 1243 1244 #usercomments, #usercommentform, #usercommentlink a, #usercommentlogoutlink a { 1245 font-family: sans-serif; 1246 font-size: 12px; 1247 } 1248 1249 #usercomments { 1250 margin: 10px 0; 1251 } 1252 1253 .usercommentheading { 1254 font-weight: bold; 1255 color: #006666; 1256 border-top: solid 1px black; 1257 } 1258 1259 .usercomment { 1260 margin: 10px 0; 1261 } 1262 1263 #usercommentlink, #usercommentlogoutlink { 1264 margin: 10px 0 20px 0; 1265 } 1266 1267 #usercommentlink a, #usercommentlogoutlink a { 1268 text-decoration: none; 1269 font-weight: bold; 1270 color: #006666; 1271 } 1272 #usercommentlink a:visited, #usercommentlogoutlink a:visited { 1273 color: #006666; 1274 } 1275 1276 .centrediv { 1277 width:50%; 1278 margin: 0 auto; 1279 } -
main/trunk/greenstone3/web/interfaces/default/transform/config_format.xsl
r31179 r31537 110 110 when the XSLT processes it (which would then result in it 111 111 being changed into a self-closing element, which then is 112 incorrectly rendered as HTML). Doing thi ngwith the112 incorrectly rendered as HTML). Doing this with the 113 113 value-of is better then injecting an xsl:comment in 114 114 (another approach we have used in the past) as the … … 116 116 HTML. This can lead to further complications if 117 117 Javascript using the 'empty' div truely expects it to 118 have no con nent of any form.118 have no content of any form. 119 119 --> 120 120 -
main/trunk/greenstone3/web/interfaces/default/transform/layouts/header.xsl
r31399 r31537 409 409 410 410 </xsl:template> 411 411 412 <xsl:template name="generateLoginURL"> 412 413 <xsl:value-of select="$library_name"/> … … 431 432 </xsl:for-each> 432 433 434 </xsl:template> 435 436 <!-- Writing the reverse of generateLoginURL since the toggleUserMenuScript does a lot more than I want. --> 437 <!-- https://www.w3schools.com/xml/xsl_functions.asp#string --> 438 <xsl:template name="generateLogoutURL"> 439 440 <xsl:variable name="url" select="/page/pageRequest/@fullURL"/> 441 <xsl:variable name="tmpURL" select="substring-before($url, '&amp;logout=')"/> 442 <xsl:variable name="beforeHash" select="substring-before($url, '#')"/> 443 <xsl:variable name="afterHash" select="substring-after($url, '#')"/> 444 <!-- Get rid of any lingering &logout= already in the URL. 445 Can't use fn:replace() as it's only been defined since XSLT 2.0. We use XSLT 1.x --> 446 <xsl:variable name="fullURL"> 447 <xsl:choose> 448 <xsl:when test="$tmpURL != ''"><xsl:value-of select="$tmpURL" /></xsl:when> 449 <xsl:otherwise><xsl:value-of select="$url" /></xsl:otherwise> 450 </xsl:choose> 451 </xsl:variable> 452 453 <!-- Output the logout link: the current page's URL (with any lingering logout suffix removed) 454 followed by ?logout= or &logout= followed by any # portion of the current page's URL --> 455 <xsl:choose> 456 <xsl:when test="$beforeHash != ''"><xsl:value-of select="$beforeHash" /></xsl:when> 457 <xsl:otherwise><xsl:value-of select="$fullURL" /></xsl:otherwise> 458 </xsl:choose> 459 <xsl:choose> 460 <xsl:when test="contains($fullURL, '?')"><xsl:text>&logout=</xsl:text></xsl:when> 461 <xsl:otherwise>?logout=</xsl:otherwise> 462 </xsl:choose> 463 <xsl:if test="$afterHash != ''">#<xsl:value-of select="$afterHash" /></xsl:if> 433 464 </xsl:template> 434 465 -
main/trunk/greenstone3/web/interfaces/default/transform/pages/document.xsl
r31534 r31537 12 12 <xsl:import href="layouts/main.xsl"/> 13 13 <xsl:import href="layouts/toc.xsl"/> 14 15 <!-- templates for adding user comments --> 16 <xsl:import href="layouts/usercomments.xsl"/> 14 17 15 18 <xsl:variable name="bookswitch"> … … 367 370 <xsl:call-template name="documentHeading"/><br/> 368 371 <xsl:call-template name="documentContent"/> 372 <br /><xsl:call-template name="userCommentsSection"/> 369 373 </xsl:when> 370 374 <xsl:otherwise> <!-- display the standard greenstone document -->
Note:
See TracChangeset
for help on using the changeset viewer.