Skip to content

Commit

Permalink
Merge pull request #1030 from HL7/2025-01-gg-no-ftp-uploads
Browse files Browse the repository at this point in the history
2025 01 gg no ftp uploads
  • Loading branch information
grahamegrieve authored Jan 30, 2025
2 parents 3595eeb + 867c41d commit e86eedc
Show file tree
Hide file tree
Showing 8 changed files with 436 additions and 317 deletions.
13 changes: 13 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
* Loader: Add missing packages to CQL list
* Loader: fix up language/local loading sequence
* Loader: fix bug for cross-version extension containing escaped [x]
* Validator: Add check for duplicate ids on contained resources
* Validator: fix bug looking up code system
* Validator: Look for cs on other server in missed location
* Validator: fix bug accessing code system from other terminology server if no version specified
* Validator: validate displaylanguage when validating codes
* Renderer: Possible fix for an NPE reported bu a user with no context
* QA: fix bug parsing `script` tag in xhtml - handling `<` characters
* QA: Tighted up handling of errors when HTML pages can't be parsed
* Publication Process: remove FTP support in -go-publish (it's all git now)
* Publication Process: radd support for creation phase
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,8 @@ private void loadFile(String s, String base, List<ValidationMessage> messages) {
} catch (FHIRFormatError | IOException e) {
x = null;
if (htmlName || !(e.getMessage().startsWith("Unable to Parse HTML - does not start with tag.") || e.getMessage().startsWith("Malformed XHTML"))) {
messages.add(new ValidationMessage(Source.LinkChecker, IssueType.STRUCTURE, s, e.getMessage(), IssueSeverity.ERROR).setLocationLink(makeLocal(f.getAbsolutePath())));
messages.add(new ValidationMessage(Source.LinkChecker, IssueType.STRUCTURE, s, e.getMessage(), IssueSeverity.ERROR).setLocationLink(makeLocal(f.getAbsolutePath())).setMessageId("HTML_PARSING_FAILED"));
missingPublishBox = true;
}
}
if (x != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.SpecialValidationAction;
import org.hl7.fhir.r5.utils.validation.constants.BindingKind;
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
Expand Down Expand Up @@ -492,4 +493,10 @@ public IValidationPolicyAdvisor getPolicyAdvisor() {
public IValidationPolicyAdvisor setPolicyAdvisor(IValidationPolicyAdvisor policyAdvisor) {
throw new Error("Not supported"); // !
}

@Override
public SpecialValidationAction policyForSpecialValidation(IResourceValidator validator, Object appContext, SpecialValidationRule rule, String stackPath, Element resource, Element element) {
return SpecialValidationAction.CHECK_RULE;

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package org.hl7.fhir.igtools.publisher.utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.json.model.JsonElement;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.json.parser.JsonParser;


public class HL7OrgFhirFixer {

public static void main(String[] args) throws IOException {
File folder = new File("/Users/grahamegrieve/web/www.hl7.org.fhir");
new HL7OrgFhirFixer().execute(folder.getAbsolutePath().length(), folder, true);
}

private void execute(int rootLen, File folder, boolean root) throws IOException {
boolean isSpec = isSpec(folder);
if (isSpec) {
System.out.print("Found Spec at "+folder.getAbsolutePath());
processSpec(rootLen, folder);
}
boolean isEmpty = true;
for (File f : folder.listFiles()) {
if (f.isDirectory()) {
isEmpty = false;
execute(rootLen, f, false);
} else if (f.getName().endsWith(".asp")) {
f.delete();
} else {
isEmpty = false;
}
}
if (isEmpty) {
folder.delete();
}
}

private boolean isSpec(File folder) throws IOException {
if (new File(Utilities.path(folder.getAbsolutePath(), "package.tgz")).exists()) {
return true;
}
if (new File(Utilities.path(folder.getAbsolutePath(), "patient.html")).exists()) {
return true;
}
if (new File(Utilities.path(folder.getAbsolutePath(), "patient.htm")).exists()) {
return true;
}
return false;
}

private void processSpec(int rootLen, File folder) throws IOException {
Map<String, Map<String, String>> list = new HashMap<>();

scanFolder(rootLen, folder, list);

int size = 0;
for (String t : list.keySet()) {
size += list.get(t).size();
String tf = Utilities.noString(t) ? folder.getAbsolutePath() : Utilities.path(folder.getAbsolutePath(), t);
Utilities.createDirectoryNC(tf);
Map<String, String> map = list.get(t);
for (String id : map.keySet()) {
String idf = Utilities.path(tf, id);
Utilities.createDirectoryNC(idf);
String rf = Utilities.path(idf, "index.php");
TextFile.stringToFile(genRedirect(map.get(id)), rf);
}
}
System.out.println(" "+size+" resources");
}

private String genRedirect(String url) {
String ub = url.replace(".json", "");
return "<?php\r\n"+
"function Redirect($url)\r\n"+
"{\r\n"+
" header('Location: ' . $url, true, 302);\r\n"+
" exit();\r\n"+
"}\r\n"+
"\r\n"+
"$accept = $_SERVER['HTTP_ACCEPT'];\r\n"+
"if (strpos($accept, 'application/json+fhir') !== false)\r\n"+
" Redirect('/fhir"+ub+".json2');\r\n"+
"elseif (strpos($accept, 'application/fhir+json') !== false)\r\n"+
" Redirect('/fhir"+ub+".json1');\r\n"+
"elseif (strpos($accept, 'json') !== false)\r\n"+
" Redirect('/fhir"+ub+".json');\r\n"+
"elseif (strpos($accept, 'application/xml+fhir') !== false)\r\n"+
" Redirect('/fhir"+ub+".xml2');\r\n"+
"elseif (strpos($accept, 'application/fhir+xml') !== false)\r\n"+
" Redirect('/fhir"+ub+".xml1');\r\n"+
"elseif (strpos($accept, 'html') !== false)\r\n"+
" Redirect('/fhir"+ub+".html');\r\n"+
"else \r\n"+
" Redirect('/fhir"+ub+".json');\r\n"+
"?>\r\n"+
"\r\n"+
"You should not be seeing this page. If you do, PHP has failed badly.\r\n"+
"\r\n";
}

private void scanFolder(int rootLen, File folder, Map<String, Map<String, String>> list) throws IOException {
for (File f : folder.listFiles()) {
if (f.getName().equals("web.config")) {
f.delete();
} else if (f.getName().endsWith(".asp")) {
f.delete();
} else if (f.isDirectory()) {
if (!isSpec(folder)) {
scanFolder(rootLen, f, list);
}
} else if (f.getName().endsWith(".json") && !f.getName().contains(".canonical.")) {
try {
JsonElement je = JsonParser.parse(f);
if (je.isJsonObject()) {
JsonObject j = je.asJsonObject();
if (j.has("resourceType") && j.has("id")) {
String rt = j.asString("resourceType");
String id = j.asString("id");
String link = f.getAbsolutePath().substring(rootLen);
Map<String, String> ft = makeMapForType(list, rt);
ft.put(id, link);
if (j.has("url")) {
String url = j.asString("url");
if (url.startsWith("http://hl7.org/fhir/")) {
String tail = url.substring(20);
if (j.has("version")) {
ft.put(id+"|"+j.asString("version"), link);
}
if (!tail.contains("/") && !tail.contains(".")) {
ft = makeMapForType(list, "");
ft.put(tail, link);
if (j.has("version")) {
ft.put(tail+"|"+j.asString("version"), link);
}
}
}
}
}
}
} catch (Exception e) {
}
}
}
}

public Map<String, String> makeMapForType(Map<String, Map<String, String>> list, String rt) {
Map<String, String> ft = list.get(rt);
if (ft == null) {
ft = new HashMap<String, String>();
list.put(rt, ft);
}
return ft;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.hl7.fhir.igtools.publisher.utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;

public class HL7OrgFhirFixerForExtensions {

public static void main(String[] args) throws IOException {
File folderRoot = new File("/Users/grahamegrieve/web/www.hl7.org.fhir");
File folderExt = new File("/Users/grahamegrieve/web/www.hl7.org.fhir/extensions");
new HL7OrgFhirFixerForExtensions().execute(folderRoot, folderExt);
}

private void execute(File folderRoot, File folderExt) throws IOException {

scanForEmptyFolders(folderRoot);
}

private void scanForEmptyFolders(File ff) throws IOException {
boolean indexed = false;
for (File f : ff.listFiles()) {
if (f.isDirectory()) {
if (!Utilities.existsInList(f.getName(), "assets", "assets-hist", "dist", "dist-hist", "less", "images", "less-glyphicons", "less-joyo", "html", "css",
"quick", "qicore", "external", "examples", "sid", ".git", "ehrsrle")) {
scanForEmptyFolders(f);
}
} else {
if (Utilities.existsInList(f.getName(), "index.html", "index.php", "web.config", ".no.index")) {
indexed = true;
}
if (f.getName().equals(".no.index")) {
f.delete();
}
if (f.getName().equals("web.config")) {
String s = TextFile.fileToString(f);
String url = s.substring(s.indexOf("destination=")+13);
url = url.substring(0, url.indexOf("\""));
String rf = genRedirect(url.replace("http://hl7.org/fhir", ""));
String dst = Utilities.path(ff, "index.php");
TextFile.stringToFile(rf, dst);
f.delete();
}
}
}
}

private boolean lowerCaseHtmlExists(File ff) throws IOException {
String path = Utilities.path(ff.getParentFile(), ff.getName().toLowerCase()+".html");
return new File(path).exists();
}

private String genRedirect(String url) {
return "<?php\r\n"+
"function Redirect($url)\r\n"+
"{\r\n"+
" header('Location: ' . $url, true, 302);\r\n"+
" exit();\r\n"+
"}\r\n"+
"\r\n"+
"$accept = $_SERVER['HTTP_ACCEPT'];\r\n"+
"if (strpos($accept, 'html') !== false)\r\n"+
" Redirect('/fhir"+url+"');\r\n"+
"else \r\n"+
" header($_SERVER[\"SERVER_PROTOCOL\"].\" 404 Not Found\");\r\n"+
"?>\r\n"+
"\r\n"+
"{ \"message\" : \"not-found\" }\r\n"+
"\r\n";
}

private boolean isResourceName(String name) {
return Utilities.existsInList(name,
"Account", "ActivityDefinition", "ActorDefinition", "AdministrableProductDefinition", "AdverseEvent", "AllergyIntolerance", "Appointment", "AppointmentResponse", "ArtifactAssessment", "AuditEvent",
"Basic", "Binary", "BiologicallyDerivedProduct", "BiologicallyDerivedProductDispense", "BodySite", "BodyStructure", "Bundle", "CanonicalResource", "CapabilityStatement", "CarePlan", "CareTeam",
"CatalogEntry", "ChargeItem", "ChargeItemDefinition", "Citation", "Claim", "ClaimResponse", "ClinicalImpression", "ClinicalUseDefinition", "CodeSystem", "Communication", "CommunicationRequest",
"CompartmentDefinition", "Composition", "ConceptMap", "Condition", "ConditionDefinition", "Conformance", "Consent", "Contract", "Coverage", "CoverageEligibilityRequest", "CoverageEligibilityResponse",
"DataElement", "DetectedIssue", "Device", "DeviceAssociation", "DeviceComponent", "DeviceDefinition", "DeviceDispense", "DeviceMetric", "DeviceRequest", "DeviceUsage", "DeviceUseRequest",
"DeviceUseStatement", "DiagnosticOrder", "DiagnosticReport", "DocumentManifest", "DocumentReference", "DomainResource", "EffectEvidenceSynthesis", "EligibilityRequest", "EligibilityResponse",
"Encounter", "EncounterHistory", "Endpoint", "EnrollmentRequest", "EnrollmentResponse", "EpisodeOfCare", "EventDefinition", "Evidence", "EvidenceReport", "EvidenceVariable", "ExampleScenario",
"ExpansionProfile", "ExplanationOfBenefit", "FamilyMemberHistory", "Flag", "FormularyItem", "GenomicStudy", "Goal", "GraphDefinition", "Group", "GuidanceResponse", "HealthcareService", "ImagingManifest",
"ImagingObjectSelection", "ImagingSelection", "ImagingStudy", "Immunization", "ImmunizationEvaluation", "ImmunizationRecommendation", "ImplementationGuide", "Ingredient", "InsurancePlan", "InventoryItem",
"InventoryReport", "Invoice", "Library", "Linkage", "List", "Location", "ManufacturedItemDefinition", "Measure", "MeasureReport", "Media", "Medication", "MedicationAdministration", "MedicationDispense",
"MedicationKnowledge", "MedicationOrder", "MedicationPrescription", "MedicationRequest", "MedicationStatement", "MedicationUsage", "MedicinalProduct", "MedicinalProductAuthorization", "MedicinalProductContraindication",
"MedicinalProductDefinition", "MedicinalProductIndication", "MedicinalProductIngredient", "MedicinalProductInteraction", "MedicinalProductManufactured", "MedicinalProductPackaged",
"MedicinalProductPharmaceutical", "MedicinalProductUndesirableEffect", "MessageDefinition", "MessageHeader", "MetadataResource", "MolecularSequence", "NamingSystem", "NutritionIntake", "NutritionOrder",
"NutritionProduct", "Observation", "ObservationDefinition", "OperationDefinition", "OperationOutcome", "Order", "OrderResponse", "Organization", "OrganizationAffiliation", "PackagedProductDefinition",
"Parameters", "Patient", "PaymentNotice", "PaymentReconciliation", "Permission", "Person", "PlanDefinition", "Practitioner", "PractitionerRole", "Procedure", "ProcedureRequest", "ProcessRequest",
"ProcessResponse", "Provenance", "Questionnaire", "QuestionnaireResponse", "ReferralRequest", "RegulatedAuthorization", "RelatedPerson", "RequestGroup", "RequestOrchestration", "Requirements",
"ResearchDefinition", "ResearchElementDefinition", "ResearchStudy", "ResearchSubject", "Resource", "RiskAssessment", "RiskEvidenceSynthesis", "Schedule", "SearchParameter", "Sequence", "ServiceDefinition",
"ServiceRequest", "Slot", "Specimen", "SpecimenDefinition", "StructureDefinition", "StructureMap", "Subscription", "SubscriptionStatus", "SubscriptionTopic", "Substance", "SubstanceDefinition",
"SubstanceNucleicAcid", "SubstancePolymer", "SubstanceProtein", "SubstanceReferenceInformation", "SubstanceSourceMaterial", "SubstanceSpecification", "SupplyDelivery", "SupplyRequest", "Task",
"TerminologyCapabilities", "TestPlan", "TestReport", "TestScript", "Transport", "ValueSet", "VerificationResult", "VisionPrescription",

"Supply", "Contraindication", "CapabilityStatement2", "ClinicalUseIssue", "DiagnosticRequest", "NutritionRequest",
"DecisionSupportServiceModule", "ModuleDefinition", "GuidanceRequest", "DecisionSupportRule", "ModuleMetadata", "OrderSet", "ModuleDefinition", "GuidanceRequest", "EvidenceFocus","ItemInstance"
);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ public static List<ValidationMessage> filterMessages(List<ValidationMessage> mes
Set<String> msgs = new HashSet<>();
for (ValidationMessage message : messages) {
boolean passesFilter = true;
if (canSuppressErrors || !message.getLevel().isError()) {
if ((canSuppressErrors || !message.getLevel().isError()) && (!"HTML_PARSING_FAILED".equals(message.getMessageId()))) {
if (suppressedMessages.contains(message.getDisplay(), message) || suppressedMessages.contains(message.getMessage(), message) ||
suppressedMessages.contains(message.getHtml(), message) || suppressedMessages.contains(message.getMessageId(), message) ||
suppressedMessages.contains(message.getInvId(), message)) {
Expand Down
Loading

0 comments on commit e86eedc

Please sign in to comment.