azure-pipelines-tasks-webdeployment-common 4.227.0 → 4.230.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -82,7 +82,7 @@ function getMSDeployCmdArgs(webAppPackage, webAppName, publishingProfile, remove
82
82
  msDeployCmdArgs += ' -skip:Directory=App_Data';
83
83
  }
84
84
  }
85
- additionalArguments = additionalArguments ? additionalArguments : ' ';
85
+ additionalArguments = additionalArguments ? escapeQuotes(additionalArguments) : ' ';
86
86
  msDeployCmdArgs += ' ' + additionalArguments;
87
87
  if (!(removeAdditionalFilesFlag && useWebDeploy)) {
88
88
  msDeployCmdArgs += " -enableRule:DoNotDeleteRule";
@@ -97,6 +97,99 @@ function getMSDeployCmdArgs(webAppPackage, webAppName, publishingProfile, remove
97
97
  return msDeployCmdArgs;
98
98
  }
99
99
  exports.getMSDeployCmdArgs = getMSDeployCmdArgs;
100
+ /**
101
+ * Escapes quotes in a string to ensure proper command-line parsing.
102
+ * @param {string} additionalArguments - The string to format.
103
+ * @returns {string} The formatted string with escaped quotes.
104
+ */
105
+ function escapeQuotes(additionalArguments) {
106
+ const parsedArgs = parseAdditionalArguments(additionalArguments);
107
+ const separator = ",";
108
+ const formattedArgs = parsedArgs.map(function (arg) {
109
+ let formattedArg = '';
110
+ let equalsSignEncountered = false;
111
+ for (let i = 0; i < arg.length; i++) {
112
+ const char = arg.charAt(i);
113
+ if (char == separator && equalsSignEncountered) {
114
+ equalsSignEncountered = false;
115
+ arg = arg.replace(formattedArg, escapeArg(formattedArg));
116
+ formattedArg = '';
117
+ continue;
118
+ }
119
+ if (equalsSignEncountered) {
120
+ formattedArg += char;
121
+ }
122
+ if (char == '=') {
123
+ equalsSignEncountered = true;
124
+ }
125
+ }
126
+ ;
127
+ if (formattedArg.length > 0) {
128
+ arg = arg.replace(formattedArg, escapeArg(formattedArg));
129
+ }
130
+ return arg;
131
+ });
132
+ return formattedArgs.join(' ');
133
+ }
134
+ exports.escapeQuotes = escapeQuotes;
135
+ /**
136
+ * Escapes special characters in a string to ensure proper command-line parsing.
137
+ * @param {string} arg - The string to format.
138
+ * @returns {string} The formatted string with escaped characters.
139
+ */
140
+ function escapeArg(arg) {
141
+ var escapedChars = new RegExp(/[\\\^\.\*\?\-\&\|\(\)\<\>\t\n\r\f]/);
142
+ // If the argument starts with dowble quote and ends with double quote, the replace it with escaped double quotes
143
+ if (arg.startsWith('"') && arg.endsWith('"')) {
144
+ return '"\\' + arg.slice(0, arg.length - 1) + '\\""';
145
+ }
146
+ // If the argument starts with single quote and ends with single quote, then replace it with escaped double qoutes
147
+ if (arg.startsWith("'") && arg.endsWith("'")) {
148
+ return '"\\"' + arg.slice(1, arg.length - 1) + '\\""';
149
+ }
150
+ if (escapedChars.test(arg)) {
151
+ return '"\\"' + arg + '\\""';
152
+ }
153
+ return arg;
154
+ }
155
+ /**
156
+ * Parses additional arguments for the msdeploy command-line utility.
157
+ * @param {string} additionalArguments - The additional arguments to parse.
158
+ * @returns {string[]} An array of parsed arguments.
159
+ */
160
+ function parseAdditionalArguments(additionalArguments) {
161
+ var parsedArgs = [];
162
+ var isInsideQuotes = false;
163
+ for (let i = 0; i < additionalArguments.length; i++) {
164
+ var arg = '';
165
+ var qouteSymbol = '';
166
+ let char = additionalArguments.charAt(i);
167
+ // command parse start
168
+ if (char === '-') {
169
+ while (i < additionalArguments.length) {
170
+ char = additionalArguments.charAt(i);
171
+ const prevSym = additionalArguments.charAt(i - 1);
172
+ // If we reach space and we are not inside quotes, then it is the end of the argument
173
+ if (char === ' ' && !isInsideQuotes)
174
+ break;
175
+ // If we reach unescaped comma and we inside qoutes we assume that it is the end of quoted line
176
+ if (isInsideQuotes && char === qouteSymbol && prevSym !== '\\') {
177
+ isInsideQuotes = false;
178
+ qouteSymbol = '';
179
+ // If we reach unescaped comma and we are not inside qoutes we assume that it is the beggining of quoted line
180
+ }
181
+ else if (!isInsideQuotes && (char === '"' || char === "'") && prevSym !== '\\') {
182
+ isInsideQuotes = !isInsideQuotes;
183
+ qouteSymbol = char;
184
+ }
185
+ arg += char;
186
+ i += 1;
187
+ }
188
+ parsedArgs.push(arg);
189
+ }
190
+ }
191
+ return parsedArgs;
192
+ }
100
193
  function getWebDeployArgumentsString(webDeployArguments, publishingProfile) {
101
194
  return __awaiter(this, void 0, void 0, function* () {
102
195
  return getMSDeployCmdArgs(webDeployArguments.package.getPath(), webDeployArguments.appName, publishingProfile, webDeployArguments.removeAdditionalFilesFlag, webDeployArguments.excludeFilesFromAppDataFlag, webDeployArguments.takeAppOfflineFlag, webDeployArguments.virtualApplication, webDeployArguments.setParametersFile, webDeployArguments.additionalArguments, yield webDeployArguments.package.isMSBuildPackage(), webDeployArguments.package.isFolder(), webDeployArguments.useWebDeploy);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azure-pipelines-tasks-webdeployment-common",
3
- "version": "4.227.0",
3
+ "version": "4.230.0",
4
4
  "description": "Common Lib for MSDeploy Utility",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,6 +23,7 @@
23
23
  "azure-pipelines-task-lib": "^4.2.0",
24
24
  "decompress-zip": "^0.3.3",
25
25
  "ltx": "2.8.0",
26
+ "node-stream-zip": "^1.15.0",
26
27
  "q": "1.4.1",
27
28
  "winreg": "1.2.2",
28
29
  "xml2js": "0.6.2"
package/packageUtility.js CHANGED
@@ -74,15 +74,7 @@ class Package {
74
74
  isMSBuildPackage() {
75
75
  return __awaiter(this, void 0, void 0, function* () {
76
76
  if (this._isMSBuildPackage == undefined) {
77
- this._isMSBuildPackage = false;
78
- if (this.getPackageType() != PackageType.folder) {
79
- var pacakgeComponent = yield zipUtility.getArchivedEntries(this._path);
80
- if (((pacakgeComponent["entries"].indexOf("parameters.xml") > -1) || (pacakgeComponent["entries"].indexOf("Parameters.xml") > -1)) &&
81
- ((pacakgeComponent["entries"].indexOf("systemInfo.xml") > -1) || (pacakgeComponent["entries"].indexOf("systeminfo.xml") > -1)
82
- || (pacakgeComponent["entries"].indexOf("SystemInfo.xml") > -1))) {
83
- this._isMSBuildPackage = true;
84
- }
85
- }
77
+ this._isMSBuildPackage = this.getPackageType() != PackageType.folder && (yield zipUtility.checkIfFilesExistsInZip(this._path, ["parameters.xml", "systeminfo.xml"]));
86
78
  tl.debug("Is the package an msdeploy package : " + this._isMSBuildPackage);
87
79
  }
88
80
  return this._isMSBuildPackage;
package/ziputility.d.ts CHANGED
@@ -4,3 +4,4 @@ export declare function archiveFolder(folderPath: any, targetPath: any, zipName:
4
4
  * Returns array of files present in archived package
5
5
  */
6
6
  export declare function getArchivedEntries(archivedPackage: string): Promise<any>;
7
+ export declare function checkIfFilesExistsInZip(archivedPackage: string, files: string[]): any;
package/ziputility.js CHANGED
@@ -9,11 +9,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getArchivedEntries = exports.archiveFolder = exports.unzip = void 0;
12
+ exports.checkIfFilesExistsInZip = exports.getArchivedEntries = exports.archiveFolder = exports.unzip = void 0;
13
13
  const tl = require("azure-pipelines-task-lib/task");
14
14
  const path = require("path");
15
15
  const Q = require("q");
16
16
  const fs = require("fs");
17
+ const StreamZip = require("node-stream-zip");
17
18
  var DecompressZip = require('decompress-zip');
18
19
  var archiver = require('archiver');
19
20
  const deleteDir = (path) => tl.exist(path) && tl.rmRF(path);
@@ -155,3 +156,28 @@ function getArchivedEntries(archivedPackage) {
155
156
  });
156
157
  }
157
158
  exports.getArchivedEntries = getArchivedEntries;
159
+ function checkIfFilesExistsInZip(archivedPackage, files) {
160
+ let deferred = Q.defer();
161
+ for (let i = 0; i < files.length; i++) {
162
+ files[i] = files[i].toLowerCase();
163
+ }
164
+ const zip = new StreamZip({
165
+ file: archivedPackage,
166
+ storeEntries: true
167
+ });
168
+ zip.on('ready', () => {
169
+ let fileCount = 0;
170
+ for (let entry in zip.entries()) {
171
+ if (files.indexOf(entry.toLowerCase()) != -1) {
172
+ fileCount += 1;
173
+ }
174
+ }
175
+ zip.close();
176
+ deferred.resolve(fileCount == files.length);
177
+ });
178
+ zip.on('error', error => {
179
+ deferred.reject(error);
180
+ });
181
+ return deferred.promise;
182
+ }
183
+ exports.checkIfFilesExistsInZip = checkIfFilesExistsInZip;