1: /* 2: * Copyright 2001-2011 Stephen Colebourne 3: * 4: * Licensed under the Apache License, Version 2.0 (the "License"); 5: * you may not use this file except in compliance with the License. 6: * You may obtain a copy of the License at 7: * 8: * http://www.apache.org/licenses/LICENSE-2.0 9: * 10: * Unless required by applicable law or agreed to in writing, software 11: * distributed under the License is distributed on an "AS IS" BASIS, 12: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13: * See the License for the specific language governing permissions and 14: * limitations under the License. 15: */ 16: package org.joda.time.format; 17: 18: import java.util.Arrays; 19: import java.util.Locale; 20: 21: import org.joda.time.Chronology; 22: import org.joda.time.DateTimeField; 23: import org.joda.time.DateTimeFieldType; 24: import org.joda.time.DateTimeUtils; 25: import org.joda.time.DateTimeZone; 26: import org.joda.time.DurationField; 27: import org.joda.time.DurationFieldType; 28: import org.joda.time.IllegalFieldValueException; 29: 30: /** 31: * DateTimeParserBucket is an advanced class, intended mainly for parser 32: * implementations. It can also be used during normal parsing operations to 33: * capture more information about the parse. 34: * <p> 35: * This class allows fields to be saved in any order, but be physically set in 36: * a consistent order. This is useful for parsing against formats that allow 37: * field values to contradict each other. 38: * <p> 39: * Field values are applied in an order where the "larger" fields are set 40: * first, making their value less likely to stick. A field is larger than 41: * another when it's range duration is longer. If both ranges are the same, 42: * then the larger field has the longer duration. If it cannot be determined 43: * which field is larger, then the fields are set in the order they were saved. 44: * <p> 45: * For example, these fields were saved in this order: dayOfWeek, monthOfYear, 46: * dayOfMonth, dayOfYear. When computeMillis is called, the fields are set in 47: * this order: monthOfYear, dayOfYear, dayOfMonth, dayOfWeek. 48: * <p> 49: * DateTimeParserBucket is mutable and not thread-safe. 50: * 51: * @author Brian S O'Neill 52: * @author Fredrik Borgh 53: * @since 1.0 54: */ 55: public class DateTimeParserBucket { 56: 57: /** The chronology to use for parsing. */ 58: private final Chronology iChrono; 59: private final long iMillis; 60: 61: /** The parsed zone, initialised to formatter zone. */ 62: private DateTimeZone iZone; 63: /** The parsed offset. */ 64: private Integer iOffset; 65: /** The locale to use for parsing. */ 66: private Locale iLocale; 67: /** Used for parsing two-digit years. */ 68: private Integer iPivotYear; 69: /** Used for parsing month/day without year. */ 70: private int iDefaultYear; 71: 72: private SavedField[] iSavedFields = new SavedField[8]; 73: private int iSavedFieldsCount; 74: private boolean iSavedFieldsShared; 75: 76: private Object iSavedState; 77: 78: /** 79: * Constructs a bucket. 80: * 81: * @param instantLocal the initial millis from 1970-01-01T00:00:00, local time 82: * @param chrono the chronology to use 83: * @param locale the locale to use 84: * @deprecated Use longer constructor 85: */ 86: @Deprecated 87: public DateTimeParserBucket(long instantLocal, Chronology chrono, Locale locale) { 88: this(instantLocal, chrono, locale, null, 2000); 89: } 90: 91: /** 92: * Constructs a bucket, with the option of specifying the pivot year for 93: * two-digit year parsing. 94: * 95: * @param instantLocal the initial millis from 1970-01-01T00:00:00, local time 96: * @param chrono the chronology to use 97: * @param locale the locale to use 98: * @param pivotYear the pivot year to use when parsing two-digit years 99: * @since 1.1 100: * @deprecated Use longer constructor 101: */ 102: @Deprecated 103: public DateTimeParserBucket(long instantLocal, Chronology chrono, Locale locale, Integer pivotYear) { 104: this(instantLocal, chrono, locale, pivotYear, 2000); 105: } 106: 107: /** 108: * Constructs a bucket, with the option of specifying the pivot year for 109: * two-digit year parsing. 110: * 111: * @param instantLocal the initial millis from 1970-01-01T00:00:00, local time 112: * @param chrono the chronology to use 113: * @param locale the locale to use 114: * @param pivotYear the pivot year to use when parsing two-digit years 115: * @since 2.0 116: */ 117: public DateTimeParserBucket(long instantLocal, Chronology chrono, 118: Locale locale, Integer pivotYear, int defaultYear) { 119: super(); 120: chrono = DateTimeUtils.getChronology(chrono); 121: iMillis = instantLocal; 122: iZone = chrono.getZone(); 123: iChrono = chrono.withUTC(); 124: iLocale = (locale == null ? Locale.getDefault() : locale); 125: iPivotYear = pivotYear; 126: iDefaultYear = defaultYear; 127: } 128: 129: //----------------------------------------------------------------------- 130: /** 131: * Gets the chronology of the bucket, which will be a local (UTC) chronology. 132: */ 133: public Chronology getChronology() { 134: return iChrono; 135: } 136: 137: //----------------------------------------------------------------------- 138: /** 139: * Returns the locale to be used during parsing. 140: * 141: * @return the locale to use 142: */ 143: public Locale getLocale() { 144: return iLocale; 145: } 146: 147: //----------------------------------------------------------------------- 148: /** 149: * Returns the time zone used by computeMillis. 150: */ 151: public DateTimeZone getZone() { 152: return iZone; 153: } 154: 155: /** 156: * Set a time zone to be used when computeMillis is called. 157: */ 158: public void setZone(DateTimeZone zone) { 159: iSavedState = null; 160: iZone = zone; 161: } 162: 163: //----------------------------------------------------------------------- 164: /** 165: * Returns the time zone offset in milliseconds used by computeMillis. 166: * @deprecated use Integer version 167: */ 168: @Deprecated 169: public int getOffset() { 170: return (iOffset != null ? iOffset : 0); 171: } 172: 173: /** 174: * Returns the time zone offset in milliseconds used by computeMillis. 175: */ 176: public Integer getOffsetInteger() { 177: return iOffset; 178: } 179: 180: /** 181: * Set a time zone offset to be used when computeMillis is called. 182: * @deprecated use Integer version 183: */ 184: @Deprecated 185: public void setOffset(int offset) { 186: iSavedState = null; 187: iOffset = offset; 188: } 189: 190: /** 191: * Set a time zone offset to be used when computeMillis is called. 192: */ 193: public void setOffset(Integer offset) { 194: iSavedState = null; 195: iOffset = offset; 196: } 197: 198: //----------------------------------------------------------------------- 199: /** 200: * Returns the default year used when information is incomplete. 201: * <p> 202: * This is used for two-digit years and when the largest parsed field is 203: * months or days. 204: * <p> 205: * A null value for two-digit years means to use the value from DateTimeFormatterBuilder. 206: * A null value for month/day only parsing will cause the default of 2000 to be used. 207: * 208: * @return Integer value of the pivot year, null if not set 209: * @since 1.1 210: */ 211: public Integer getPivotYear() { 212: return iPivotYear; 213: } 214: 215: /** 216: * Sets the pivot year to use when parsing two digit years. 217: * <p> 218: * If the value is set to null, this will indicate that default 219: * behaviour should be used. 220: * 221: * @param pivotYear the pivot year to use 222: * @since 1.1 223: */ 224: public void setPivotYear(Integer pivotYear) { 225: iPivotYear = pivotYear; 226: } 227: 228: //----------------------------------------------------------------------- 229: /** 230: * Saves a datetime field value. 231: * 232: * @param field the field, whose chronology must match that of this bucket 233: * @param value the value 234: */ 235: public void saveField(DateTimeField field, int value) { 236: saveField(new SavedField(field, value)); 237: } 238: 239: /** 240: * Saves a datetime field value. 241: * 242: * @param fieldType the field type 243: * @param value the value 244: */ 245: public void saveField(DateTimeFieldType fieldType, int value) { 246: saveField(new SavedField(fieldType.getField(iChrono), value)); 247: } 248: 249: /** 250: * Saves a datetime field text value. 251: * 252: * @param fieldType the field type 253: * @param text the text value 254: * @param locale the locale to use 255: */ 256: public void saveField(DateTimeFieldType fieldType, String text, Locale locale) { 257: saveField(new SavedField(fieldType.getField(iChrono), text, locale)); 258: } 259: 260: private void saveField(SavedField field) { 261: SavedField[] savedFields = iSavedFields; 262: int savedFieldsCount = iSavedFieldsCount; 263: 264: if (savedFieldsCount == savedFields.length || iSavedFieldsShared) { 265: // Expand capacity or merely copy if saved fields are shared. 266: SavedField[] newArray = new SavedField 267: [savedFieldsCount == savedFields.length ? savedFieldsCount * 2 : savedFields.length]; 268: System.arraycopy(savedFields, 0, newArray, 0, savedFieldsCount); 269: iSavedFields = savedFields = newArray; 270: iSavedFieldsShared = false; 271: } 272: 273: iSavedState = null; 274: savedFields[savedFieldsCount] = field; 275: iSavedFieldsCount = savedFieldsCount + 1; 276: } 277: 278: /** 279: * Saves the state of this bucket, returning it in an opaque object. Call 280: * restoreState to undo any changes that were made since the state was 281: * saved. Calls to saveState may be nested. 282: * 283: * @return opaque saved state, which may be passed to restoreState 284: */ 285: public Object saveState() { 286: if (iSavedState == null) { 287: iSavedState = new SavedState(); 288: } 289: return iSavedState; 290: } 291: 292: /** 293: * Restores the state of this bucket from a previously saved state. The 294: * state object passed into this method is not consumed, and it can be used 295: * later to restore to that state again. 296: * 297: * @param savedState opaque saved state, returned from saveState 298: * @return true state object is valid and state restored 299: */ 300: public boolean restoreState(Object savedState) { 301: if (savedState instanceof SavedState) { 302: if (((SavedState) savedState).restoreState(this)) { 303: iSavedState = savedState; 304: return true; 305: } 306: } 307: return false; 308: } 309: 310: /** 311: * Computes the parsed datetime by setting the saved fields. 312: * This method is idempotent, but it is not thread-safe. 313: * 314: * @return milliseconds since 1970-01-01T00:00:00Z 315: * @throws IllegalArgumentException if any field is out of range 316: */ 317: public long computeMillis() { 318: return computeMillis(false, null); 319: } 320: 321: /** 322: * Computes the parsed datetime by setting the saved fields. 323: * This method is idempotent, but it is not thread-safe. 324: * 325: * @param resetFields false by default, but when true, unsaved field values are cleared 326: * @return milliseconds since 1970-01-01T00:00:00Z 327: * @throws IllegalArgumentException if any field is out of range 328: */ 329: public long computeMillis(boolean resetFields) { 330: return computeMillis(resetFields, null); 331: } 332: 333: /** 334: * Computes the parsed datetime by setting the saved fields. 335: * This method is idempotent, but it is not thread-safe. 336: * 337: * @param resetFields false by default, but when true, unsaved field values are cleared 338: * @param text optional text being parsed, to be included in any error message 339: * @return milliseconds since 1970-01-01T00:00:00Z 340: * @throws IllegalArgumentException if any field is out of range 341: * @since 1.3 342: */ 343: public long computeMillis(boolean resetFields, String text) { 344: SavedField[] savedFields = iSavedFields; 345: int count = iSavedFieldsCount; 346: if (iSavedFieldsShared) { 347: iSavedFields = savedFields = (SavedField[])iSavedFields.clone(); 348: iSavedFieldsShared = false; 349: } 350: sort(savedFields, count); 351: if (count > 0) { 352: // alter base year for parsing if first field is month or day 353: DurationField months = DurationFieldType.months().getField(iChrono); 354: DurationField days = DurationFieldType.days().getField(iChrono); 355: DurationField first = savedFields[0].iField.getDurationField(); 356: if (compareReverse(first, months) >= 0 && compareReverse(first, days) <= 0) { 357: saveField(DateTimeFieldType.year(), iDefaultYear); 358: return computeMillis(resetFields, text); 359: } 360: } 361: 362: long millis = iMillis; 363: try { 364: for (int i = 0; i < count; i++) { 365: millis = savedFields[i].set(millis, resetFields); 366: } 367: if (resetFields) { 368: for (int i = 0; i < count; i++) { 369: millis = savedFields[i].set(millis, i == (count - 1)); 370: } 371: } 372: } catch (IllegalFieldValueException e) { 373: if (text != null) { 374: e.prependMessage("Cannot parse \"" + text + '"'); 375: } 376: throw e; 377: } 378: 379: if (iOffset != null) { 380: millis -= iOffset; 381: } else if (iZone != null) { 382: int offset = iZone.getOffsetFromLocal(millis); 383: millis -= offset; 384: if (offset != iZone.getOffset(millis)) { 385: String message = 386: "Illegal instant due to time zone offset transition (" + iZone + ')'; 387: if (text != null) { 388: message = "Cannot parse \"" + text + "\": " + message; 389: } 390: throw new IllegalArgumentException(message); 391: } 392: } 393: 394: return millis; 395: } 396: 397: /** 398: * Sorts elements [0,high). Calling java.util.Arrays isn't always the right 399: * choice since it always creates an internal copy of the array, even if it 400: * doesn't need to. If the array slice is small enough, an insertion sort 401: * is chosen instead, but it doesn't need a copy! 402: * <p> 403: * This method has a modified version of that insertion sort, except it 404: * doesn't create an unnecessary array copy. If high is over 10, then 405: * java.util.Arrays is called, which will perform a merge sort, which is 406: * faster than insertion sort on large lists. 407: * <p> 408: * The end result is much greater performance when computeMillis is called. 409: * Since the amount of saved fields is small, the insertion sort is a 410: * better choice. Additional performance is gained since there is no extra 411: * array allocation and copying. Also, the insertion sort here does not 412: * perform any casting operations. The version in java.util.Arrays performs 413: * casts within the insertion sort loop. 414: */ 415: private static void sort(SavedField[] array, int high) { 416: if (high > 10) { 417: Arrays.sort(array, 0, high); 418: } else { 419: for (int i=0; i<high; i++) { 420: for (int j=i; j>0 && (array[j-1]).compareTo(array[j])>0; j--) { 421: SavedField t = array[j]; 422: array[j] = array[j-1]; 423: array[j-1] = t; 424: } 425: } 426: } 427: } 428: 429: class SavedState { 430: final DateTimeZone iZone; 431: final Integer iOffset; 432: final SavedField[] iSavedFields; 433: final int iSavedFieldsCount; 434: 435: SavedState() { 436: this.iZone = DateTimeParserBucket.this.iZone; 437: this.iOffset = DateTimeParserBucket.this.iOffset; 438: this.iSavedFields = DateTimeParserBucket.this.iSavedFields; 439: this.iSavedFieldsCount = DateTimeParserBucket.this.iSavedFieldsCount; 440: } 441: 442: boolean restoreState(DateTimeParserBucket enclosing) { 443: if (enclosing != DateTimeParserBucket.this) { 444: return false; 445: } 446: enclosing.iZone = this.iZone; 447: enclosing.iOffset = this.iOffset; 448: enclosing.iSavedFields = this.iSavedFields; 449: if (this.iSavedFieldsCount < enclosing.iSavedFieldsCount) { 450: // Since count is being restored to a lower count, the 451: // potential exists for new saved fields to destroy data being 452: // shared by another state. Set this flag such that the array 453: // of saved fields is cloned prior to modification. 454: enclosing.iSavedFieldsShared = true; 455: } 456: enclosing.iSavedFieldsCount = this.iSavedFieldsCount; 457: return true; 458: } 459: } 460: 461: static class SavedField implements Comparable<SavedField> { 462: final DateTimeField iField; 463: final int iValue; 464: final String iText; 465: final Locale iLocale; 466: 467: SavedField(DateTimeField field, int value) { 468: iField = field; 469: iValue = value; 470: iText = null; 471: iLocale = null; 472: } 473: 474: SavedField(DateTimeField field, String text, Locale locale) { 475: iField = field; 476: iValue = 0; 477: iText = text; 478: iLocale = locale; 479: } 480: 481: long set(long millis, boolean reset) { 482: if (iText == null) { 483: millis = iField.set(millis, iValue); 484: } else { 485: millis = iField.set(millis, iText, iLocale); 486: } 487: if (reset) { 488: millis = iField.roundFloor(millis); 489: } 490: return millis; 491: } 492: 493: /** 494: * The field with the longer range duration is ordered first, where 495: * null is considered infinite. If the ranges match, then the field 496: * with the longer duration is ordered first. 497: */ 498: public int compareTo(SavedField obj) { 499: DateTimeField other = obj.iField; 500: int result = compareReverse 501: (iField.getRangeDurationField(), other.getRangeDurationField()); 502: if (result != 0) { 503: return result; 504: } 505: return compareReverse 506: (iField.getDurationField(), other.getDurationField()); 507: } 508: } 509: 510: static int compareReverse(DurationField a, DurationField b) { 511: if (a == null || !a.isSupported()) { 512: if (b == null || !b.isSupported()) { 513: return 0; 514: } 515: return -1; 516: } 517: if (b == null || !b.isSupported()) { 518: return 1; 519: } 520: return -a.compareTo(b); 521: } 522: }
| ID | Line | Type | Detected |
|---|---|---|---|
| 12894 | 72 | Replace a constant (Replace 8 with 9(INT)) | |
| 12893 | 72 | Replace a constant (Replace 8 with 7(INT)) | |
| 12892 | 72 | Replace a constant (Replace 8 with 0(INT)) | |
| 12887 | 88 | Replace a constant (Replace 2000 with 1999(INT)) | |
| 12886 | 88 | Replace a constant (Replace 2000 with 0(INT)) | |
| 12888 | 88 | Replace a constant (Replace 2000 with 2001(INT)) | |
| 12891 | 104 | Replace a constant (Replace 2000 with 2001(INT)) | |
| 12890 | 104 | Replace a constant (Replace 2000 with 1999(INT)) | |
| 12889 | 104 | Replace a constant (Replace 2000 with 0(INT)) | |
| 12895 | 120 | Remove method call | |
| 12896 | 122 | Remove method call | |
| 12897 | 123 | Remove method call | |
| 12898 | 124 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 12899 | 124 | Remove method call | |
| 12903 | 170 | Replace a constant (Replace 0 with -1(INT)) | |
| 12902 | 170 | Replace a constant (Replace 0 with 1(INT)) | |
| 12900 | 170 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 12901 | 170 | Remove method call | |
| 12904 | 187 | Remove method call | |
| 12905 | 236 | Remove method call | |
| 12906 | 246 | Remove method call | |
| 12907 | 246(1) | Remove method call | |
| 12908 | 257 | Remove method call | |
| 12909 | 257(1) | Remove method call | |
| 12910 | 264 | Negate jump condition (Replace IF_ICMPEQ with IF_ICMPNE) | |
| 12911 | 264(1) | Negate jump condition (Replace IFEQ with IFNE) | |
| 12914 | 266 | Replace a constant (Replace 2 with 1(INT)) | |
| 12915 | 266 | Replace a constant (Replace 2 with 0(INT)) | |
| 12913 | 266 | Replace a constant (Replace 2 with 3(INT)) | |
| 12912 | 266 | Negate jump condition (Replace IF_ICMPNE with IF_ICMPEQ) | |
| 12916 | 266 | Replace arithmetic operator (Replace IMUL with IADD) | |
| 12918 | 268 | Replace a constant (Replace 0 with -1(INT)) | |
| 12917 | 268 | Replace a constant (Replace 0 with 1(INT)) | |
| 12919 | 268(1) | Replace a constant (Replace 0 with 1(INT)) | |
| 12920 | 268(1) | Replace a constant (Replace 0 with -1(INT)) | |
| 12921 | 268 | Remove method call | |
| 12923 | 270 | Replace a constant (Replace 0 with -1(INT)) | |
| 12922 | 270 | Replace a constant (Replace 0 with 1(INT)) | |
| 12924 | 275 | Replace a constant (Replace 1 with 2(INT)) | |
| 12925 | 275 | Replace a constant (Replace 1 with 0(INT)) | |
| 12926 | 275 | Replace arithmetic operator (Replace IADD with ISUB) | |
| 12927 | 286 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 12928 | 301 | Negate jump condition (Replace IFEQ with IFNE) | |
| 12930 | 302 | Negate jump condition (Replace IFEQ with IFNE) | |
| 12929 | 302 | Remove method call | |
| 12931 | 304 | Replace a constant (Replace 1 with 2(INT)) | |
| 12932 | 304 | Replace a constant (Replace 1 with 0(INT)) | |
| 12933 | 307 | Replace a constant (Replace 0 with 1(INT)) | |
| 12934 | 307 | Replace a constant (Replace 0 with -1(INT)) | |
| 12935 | 318 | Replace a constant (Replace 0 with 1(INT)) | |
| 12936 | 318 | Replace a constant (Replace 0 with -1(INT)) | |
| 12937 | 318 | Remove method call | |
| 12938 | 330 | Remove method call | |
| 12939 | 346 | Negate jump condition (Replace IFEQ with IFNE) | |
| 12940 | 347 | Remove method call | |
| 12941 | 348 | Replace a constant (Replace 0 with 1(INT)) | |
| 12942 | 348 | Replace a constant (Replace 0 with -1(INT)) | |
| 12943 | 350 | Remove method call | |
| 12944 | 351 | Negate jump condition (Replace IFLE with IFGT) | |
| 12945 | 353 | Remove method call | |
| 12946 | 353(1) | Remove method call | |
| 12947 | 354 | Remove method call | |
| 12948 | 354(1) | Remove method call | |
| 12949 | 355 | Replace a constant (Replace 0 with 1(INT)) | |
| 12950 | 355 | Replace a constant (Replace 0 with -1(INT)) | |
| 12951 | 355 | Remove method call | |
| 12953 | 356 | Negate jump condition (Replace IFLT with IFGE) | |
| 12955 | 356(1) | Negate jump condition (Replace IFGT with IFLE) | |
| 12952 | 356 | Remove method call | |
| 12954 | 356(1) | Remove method call | |
| 12956 | 357 | Remove method call | |
| 12957 | 357(1) | Remove method call | |
| 12958 | 358 | Remove method call | |
| 12960 | 364 | Replace a constant (Replace 0 with -1(INT)) | |
| 12959 | 364 | Replace a constant (Replace 0 with 1(INT)) | |
| 12961 | 364 | Negate jump condition (Replace IF_ICMPGE with IF_ICMPLT) | |
| 12962 | 365 | Remove method call | |
| 12963 | 367 | Negate jump condition (Replace IFEQ with IFNE) | |
| 12964 | 368 | Replace a constant (Replace 0 with 1(INT)) | |
| 12965 | 368 | Replace a constant (Replace 0 with -1(INT)) | |
| 12966 | 368 | Negate jump condition (Replace IF_ICMPGE with IF_ICMPLT) | |
| 12968 | 369 | Replace a constant (Replace 1 with 0(INT)) | |
| 12967 | 369 | Replace a constant (Replace 1 with 2(INT)) | |
| 12972 | 369(1) | Replace a constant (Replace 1 with 0(INT)) | |
| 12971 | 369(1) | Replace a constant (Replace 1 with 2(INT)) | |
| 12973 | 369(2) | Replace a constant (Replace 0 with 1(INT)) | |
| 12974 | 369(2) | Replace a constant (Replace 0 with -1(INT)) | |
| 12970 | 369 | Negate jump condition (Replace IF_ICMPNE with IF_ICMPEQ) | |
| 12969 | 369 | Replace arithmetic operator (Replace ISUB with IADD) | |
| 12975 | 369 | Remove method call | |
| 12976 | 373 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 12979 | 374 | Replace a constant (Replace 34 with 0(INT)) | |
| 12980 | 374 | Replace a constant (Replace 34 with 35(INT)) | |
| 12981 | 374 | Replace a constant (Replace 34 with 33(INT)) | |
| 12977 | 374 | Remove method call | |
| 12978 | 374(1) | Remove method call | |
| 12982 | 374(2) | Remove method call | |
| 12983 | 374(3) | Remove method call | |
| 12984 | 374(4) | Remove method call | |
| 12985 | 379 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 12987 | 380 | Replace arithmetic operator (Replace LSUB with LADD) | |
| 12986 | 380 | Remove method call | |
| 12988 | 381 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 12989 | 382 | Remove method call | |
| 12990 | 383 | Replace arithmetic operator (Replace LSUB with LADD) | |
| 12992 | 384 | Negate jump condition (Replace IF_ICMPEQ with IF_ICMPNE) | |
| 12991 | 384 | Remove method call | |
| 12996 | 385 | Replace a constant (Replace 41 with 42(INT)) | |
| 12997 | 385 | Replace a constant (Replace 41 with 40(INT)) | |
| 12995 | 385 | Replace a constant (Replace 41 with 0(INT)) | |
| 12993 | 385 | Remove method call | |
| 12994 | 385(1) | Remove method call | |
| 12998 | 385(2) | Remove method call | |
| 12999 | 385(3) | Remove method call | |
| 13000 | 387 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 13001 | 388 | Remove method call | |
| 13002 | 388(1) | Remove method call | |
| 13003 | 388(2) | Remove method call | |
| 13004 | 388(3) | Remove method call | |
| 13005 | 388(4) | Remove method call | |
| 13006 | 416 | Replace a constant (Replace 10 with 0(INT)) | |
| 13007 | 416 | Replace a constant (Replace 10 with 9(INT)) | |
| 13008 | 416 | Replace a constant (Replace 10 with 11(INT)) | |
| 13009 | 416 | Negate jump condition (Replace IF_ICMPLE with IF_ICMPGT) | |
| 13011 | 417 | Replace a constant (Replace 0 with -1(INT)) | |
| 13010 | 417 | Replace a constant (Replace 0 with 1(INT)) | |
| 13012 | 417 | Remove method call | |
| 13014 | 419 | Replace a constant (Replace 0 with -1(INT)) | |
| 13013 | 419 | Replace a constant (Replace 0 with 1(INT)) | |
| 13015 | 419 | Negate jump condition (Replace IF_ICMPGE with IF_ICMPLT) | |
| 13018 | 420 | Replace a constant (Replace 1 with 0(INT)) | |
| 13017 | 420 | Replace a constant (Replace 1 with 2(INT)) | |
| 13016 | 420 | Negate jump condition (Replace IFLE with IFGT) | |
| 13021 | 420(1) | Negate jump condition (Replace IFLE with IFGT) | |
| 13019 | 420 | Replace arithmetic operator (Replace ISUB with IADD) | |
| 13020 | 420 | Remove method call | |
| 13023 | 422 | Replace a constant (Replace 1 with 0(INT)) | |
| 13022 | 422 | Replace a constant (Replace 1 with 2(INT)) | |
| 13024 | 422 | Replace arithmetic operator (Replace ISUB with IADD) | |
| 13025 | 423 | Replace a constant (Replace 1 with 2(INT)) | |
| 13026 | 423 | Replace a constant (Replace 1 with 0(INT)) | |
| 13027 | 423 | Replace arithmetic operator (Replace ISUB with IADD) | |
| 19778 | 436 | Remove method call | |
| 19779 | 437 | Remove method call | |
| 19780 | 438 | Remove method call | |
| 19781 | 439 | Remove method call | |
| 19782 | 443 | Negate jump condition (Replace IF_ACMPEQ with IF_ACMPNE) | |
| 19783 | 444 | Replace a constant (Replace 0 with 1(INT)) | |
| 19784 | 444 | Replace a constant (Replace 0 with -1(INT)) | |
| 19785 | 446 | Remove method call | |
| 19786 | 447 | Remove method call | |
| 19787 | 448 | Remove method call | |
| 19789 | 449 | Negate jump condition (Replace IF_ICMPGE with IF_ICMPLT) | |
| 19788 | 449 | Remove method call | |
| 19790 | 454 | Replace a constant (Replace 1 with 2(INT)) | |
| 19791 | 454 | Replace a constant (Replace 1 with 0(INT)) | |
| 19792 | 454 | Remove method call | |
| 19793 | 456 | Remove method call | |
| 19794 | 457 | Replace a constant (Replace 1 with 2(INT)) | |
| 19795 | 457 | Replace a constant (Replace 1 with 0(INT)) | |
| 13045 | 476 | Replace a constant (Replace 0 with 1(INT)) | |
| 13046 | 476 | Replace a constant (Replace 0 with -1(INT)) | |
| 13047 | 482 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 13048 | 483 | Remove method call | |
| 13049 | 485 | Remove method call | |
| 13050 | 487 | Negate jump condition (Replace IFEQ with IFNE) | |
| 13051 | 488 | Remove method call | |
| 13052 | 500 | Remove method call | |
| 13053 | 500(1) | Remove method call | |
| 13054 | 500(2) | Remove method call | |
| 13055 | 502 | Negate jump condition (Replace IFEQ with IFNE) | |
| 13056 | 505 | Remove method call | |
| 13057 | 505(1) | Remove method call | |
| 13058 | 505(2) | Remove method call | |
| 13028 | 511 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 13030 | 511(1) | Negate jump condition (Replace IFNE with IFEQ) | |
| 13029 | 511 | Remove method call | |
| 13031 | 512 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 13033 | 512(1) | Negate jump condition (Replace IFNE with IFEQ) | |
| 13032 | 512 | Remove method call | |
| 13034 | 513 | Replace a constant (Replace 0 with 1(INT)) | |
| 13035 | 513 | Replace a constant (Replace 0 with -1(INT)) | |
| 13036 | 515 | Replace a constant (Replace -1 with 0(INT)) | |
| 13037 | 515 | Replace a constant (Replace -1 with -2(INT)) | |
| 13038 | 517 | Negate jump condition (Replace IFNULL with IFNONNULL) | |
| 13040 | 517(1) | Negate jump condition (Replace IFNE with IFEQ) | |
| 13039 | 517 | Remove method call | |
| 13041 | 518 | Replace a constant (Replace 1 with 2(INT)) | |
| 13042 | 518 | Replace a constant (Replace 1 with 0(INT)) | |
| 13044 | 520 | Replace arithmetic operator (Replace INEG with remove right opereand) | |
| 13043 | 520 | Remove method call |


Before Change
images = ((img["default.tif"], img["userdata.json"]) for img in images)
images = [(img, meta.get("norm_factor", 0)) for img, meta in images]
for f_type, f_name_src, f_name_dst in self.additional_data:
eopatch[(f_type, f_name_dst)] = self._extract_additional_data(images, f_type, f_name_src, shape)
After Change
Extract data from the received images and assign them to eopatch features
rtypes = [rtype for rtype in self.request_types if rtype.id != "bands"]
itr_tifs = ((rtype, [img[rtype.id + ".tif"] for img in images], self.request_types[rtype]) for rtype in rtypes)
for rtype, tifs, bands in itr_tifs:
for band in bands:
feature = rtype.feature_type, band
eopatch[feature] = self._extract_array(tifs, bands.index(band), shape, rtype.np_dtype)
if self.bands_feature:
self._extract_bands_feature(eopatch, images, shape)
return eopatch


.d8888b. .d8888b. 8888888 d88P Y88b d88P Y88b 888 888 888 888 888 888 888 888 888<PHONE_NUMBER>8 888 888 888 888 888 888 Y88b d88P Y88b d88P 888 "Y8888P" "Y8888P88 8888888 PCP => Perl CGI Program (ming) Version 1.0
--tchrist
There are times when you might want to have some dynamic information (information that's not constant) in your HTML documents. This could include simple information such as the date and time, or a counter that displays "You are visitor number xxx", but it could also include such things as pie charts/graphs based on user input, results from searching a database, or animations. And the only way you can produce results like these is with CGI scripts (though you can also do so with client side applications like Java and JavaScript, but that's a totally different story!)
Here is an excellent description that my editors Andy Oram and Linda Mui (they're great!) wrote up:
Common Assures you that CGI can be used by many languages and interact with many different types of systems. It doesn't tie you down to one way of doing what you want. Gateway Suggests that CGI's strength lies not in what it does by itself, but in the potential access it offers to other systems such as databases and graphic generators. Interface Simply means that CGI provides a well-defined way to call up its features--in other words, that you can write programs that use it.
Simply put, a script is a program! OK, OK, there are semantical differences between the two terms. If you really want to know, pick up a book on computer programming (or is that computer scripting :-)
You can create a lot of magic by writing a CGI program/script. You can create graphics on the fly, access databases and return results and connect to other Internet information servers.
The answer is located in the first three lines of the Perl manpage:
Perl is an interpreted language optimized for scanning arbitrary text files, extracting information from those text files, and printing reports based on that information.Most CGI applications involve manipulating data in some fashion and accessing external programs and applications. Perl provides easy to use tools that make these tasks a cinch.
Here is a list of books on CGI and Perl compiled by Cye H. Waldman:
---------------+---------------------------------+--------------+-------+------ Author | Title | Publisher | Media | Price ---------------+---------------------------------+--------------+-------+------ Christian | The Webmaster's Handbook: | Int. Thomson | CD | $30 Neuss & | Perl Power for Your Web Server | | | Johan Vromans | | | | ---------------+---------------------------------+--------------+-------+------ William E. | CGI Scripting | New Riders | CD | $45 Weinman | | | | ---------------+---------------------------------+--------------+-------+------ Garbus et al. | Perl Programming Unleashed | Sams.net | CD | | (Available Mar 1996) | | | ---------------+---------------------------------+--------------+-------+------ Steven E. | Introduction to CGI & Perl: | MIS Press | | Brenner | Web Scripts: | | | Edwin Aoki | | | | ---------------+---------------------------------+--------------+-------+------ Ed Tittel | Perl 5 Programming Secrets | IDG Books | CD | et al. | (Available Mar 1996) | | | ---------------+---------------------------------+--------------+-------+------ Mitzelfelt | Special Edition Using Perl | Que | | ---------------+---------------------------------+--------------+-------+------ Shishir | CGI Programming on the | O'Reilly | | $30 Gundavaram | World Wide Web | | | ---------------+---------------------------------+--------------+-------+------ Rob Farrel | The Official 60 Minute Guide | IDG Books | | $20 | to CGI Programming with Perl | | | ---------------+---------------------------------+--------------+-------+------ Ed Tittel | Web Programming Secrets | IDG Books | CD | $40 et al. | | | | ---------------+---------------------------------+--------------+-------+------ John Deep | Developing CGI Applications | Wiley | | $30 | with Perl | | | ---------------+---------------------------------+--------------+-------+------ Jon Orwant | Perl 5 Interactive | Waite | | $30 ---------------+---------------------------------+--------------+-------+------ Reggie David | Perl 5 How-To | Waite | CD | $40 | (Available Spring 1996) | | | ---------------+---------------------------------+--------------+-------+------ Eric Herrmann | Teach Yourself CGI | Sams.net | | $30 | Programming with Perl in a | | | | Week | | | ---------------+---------------------------------+--------------+-------+------ Walnut Creek | Perl (Collected resources, | Walnut Creek | CD | $40 CD-ROM | archives, tutorial, examples, | | | | source code,etc.) | | | ---------------+---------------------------------+--------------+-------+------ Carl Dichter & | Software Engineering with | | | Mark Pease | Perl | | | | (This is an advanced text for | Prentice | Disk | $30 | software professionals; it is | Hall | | | not a tutorial) | | | ---------------+---------------------------------+--------------+-------+------ Ellie Quigley | Perl by Example | Prentice | | $27 | | Hall | | ---------------+---------------------------------+--------------+-------+------ John December | HTML & CGI Unleashed | Sams.net | CD | $50 Mark Ginsburg | | | | ---------------+---------------------------------+--------------+-------+------ David Till | Teach Yourself Perl in 21 | Sams | | $30 | Days | | | ---------------+---------------------------------+--------------+-------+------ Larry Wall & | Programming Perl | O'Reilly | | $30 Randal L. | | | | Schwartz | | | | ---------------+---------------------------------+--------------+-------+------ Randal L. | Learning Perl | O'Reilly | | $25 Schwartz | | | | ---------------+---------------------------------+--------------+-------+------ Ed Tittel | Foundations of WWW | IDG Books | CD | $40 et al. | Programming with HTML and CGI | | | ---------------+---------------------------------+--------------+-------+------ Eric Lease | Teaching a New Dog Old Tricks | | | FREE! Morgan | (Mac-based WWW Starter Kit | | | | with Server) | | | ---------------+---------------------------------+--------------+-------+------ Susan Peck & | Website: Everything You Need | O'Reilly | CD | $500 Linda Mui | to Know... | | | | (This is a complete Website | | | | kit for Windows NT 3.5) | | | ---------------+---------------------------------+--------------+-------+------ Lincoln D. | How to Set Up and Maintain a | Addison | | $29 Stein | World Wide Web Site | Wesley | | ---------------+---------------------------------+--------------+-------+------ Jonathan | The Web Server Book | Ventana | CD | $50 Magid et al. | | | | ---------------+---------------------------------+--------------+-------+------ net.Genesis & | Build a Web Site | Prima | | $35 Devra Hall | | | | ---------------+---------------------------------+--------------+-------+------ David | Running a Perfect Web Site | Que | CD | $40 Chandler | | | | ---------------+---------------------------------+--------------+-------+------ Jon Weiderspan | Planning & Managing a Web | Addison | CD | $40 Chuck Shotton | Site on the Macintosh | Wesley | | ---------------+---------------------------------+--------------+-------+------
There is a very useful newsgroup: comp.infosystems.www.authoring.cgi, that's "monitored" by numerous CGI experts. However, you should not post a question to this group (or any other group, for that matter), until you have read the FAQ.
Various mailing lists for Perl, CGI, and the Web exist. Here are two of the most popular:
CPAN: Perl modules may also be retrieved from the multiplexed distributed CPAN system. This chooses a "site near you". For example, LWP modules are retrievable as source or just the readme.
Yes, look at The Usenet Newstand, which has all of the comp.infosystems.www.* newsgroups are archived. In addition, the cgi-perl and libwww mailing lists are archived there as well.
It really depends on what you are trying to do. The CGI modules should generally be used for heavy-duty CGI scripts. For simple scripts, its is far easier and quicker to roll your own or use CGI Lite (current version is v1.62). If you really want, you can even use the old Perl 4 cgi-lib.pl library.
Most modules have manpages embedded within the module itself. If that's the case, you can use the pod2man script to view the manpage:
% pod2text name_of_module.pm
% pod2man name_of_module.pm | nroff -man | more
The most widely used CGI library for Perl 4 is cgi-lib.pl written by Steven Benner.
Lincoln has also written an excellent book on the Web and CGI, titled How to Set Up and Maintain a World Wide Web Site.
All three of these modules have the ability to decode the multipart form data (i.e file upload).
Actually, it's not very hard at all. See Tom Christiansen's Easy Intro to Using Perl Objects for a quick primer.
The CGI modules mentioned above are a piece of cake to use! Here is a simple example that uses CGI Lite to print out form data:
Note, if you did not build Perl on your system or do not have access to install these modules with the other Perl library files, you can still use it by placing the module in a convenient place and adding the following to your script:#!/usr/local/bin/perl5 use CGI_Lite; $cgi = new CGI_Lite; %data = $cgi->parse_form_data; print "Content-type: text/plain", "\n\n"; foreach $key (keys %data) { print $key, " = ", $data{$key}, "\n"; } exit (0);
Now, here is an example using the CGI::* modules:BEGIN { unshift (@INC, "/your/dir/favorite/place"); }
#!/usr/local/bin/perl5 use CGI::Form; $cgi_form = new CGI::Form; print <<'End_of_Header';  <TITLE>Watch This!</TITLE>
Watch This!
 End_of_Header print $form->startform; ## Creates a text field print "Name: "; print $form->textfield('name'), "
\n"; ## Creates a group of radio buttons print "
Where do you live:
"; print $form->radio_group (-name => 'where', -values => ['North America', 'South America', 'Europe', 'Australia', 'Asia', 'Antartica'], -default => 'North America', -linebreak => 'true'); ## Creates a textarea field print "Comments: "; print $form->textarea('comments', undef, 5, 40); print "
"; print $form->reset; print $form->defaults; print $form->submit ('Send!', 'Submit'); print $form->endform; print "";
The reset, defaults and submit methods create different type of buttons. The reset button allows you to clear the values in the current form and display values from the previous state (or session). The defaults button clears the form entirely. And the submit method creates a Submit button for you to send the data to the server.
Now, wasn't that simple?
The server is generally configured so that it executes CGI scripts that are located in the "cgi-bin" directory. However, the server administrator can set up aliases in the server configuration files, so that scripts with certain extensions (i.e .cgi, .pl) can also be executed.
File permissions allow read, write, and execute access to users based on their user identification (also known as uid), and their membership to certain groups. You can use the command: chmod to change a file's permissions. Here is an example:
This has a permission of 0700 (octal), which means that no one (besides the owner) can read to, write from, and execute this file. Let's use the chmod command to change the permissions:% ls -ls form.cgi 1 -rwx------ 1 shishir 974 Oct 31 22:15 form.cgi*
This changes the permissions so that users in the same group as "shishir", as well as all other users have the permission to read from, and execute this file.% chmod 755 form.cgi % ls -ls form.cgi 1 -rwxr-xr-x 1 shishir 974 Oct 31 22:15 form.cgi*
See the manpages for the chmod command for a full explanation of the various octal codes.
Perl can be installed anywhere on the system! The only thing you have to make sure is that the server is not running in a chroot-ed environment, and that it can access the interpreter. In other words, system administrators can change the root directory, so that "/" does not point to the actual root ("/"), but to another directory.
You can get a server error for the following reasons:
Generally, the HTTP server will be running as user "nobody", or "www", or some other user id that has mimimal privileges. As a result, the directory (where you intend to create the file) must be writeable by this process id.
To be on the safe side, always check the return status from the open command to see if it was a success:
open (FILE, "/abc/data.txt") || error ("Could not open file /abc/data.txt"); . . . sub error { my ($message) = @_; print <<End_of_Error; Content-type: text/html Status: 500 CGI Error  <TITLE>CGI Error</TITLE>
Oops! Error

 $message
   End_of_Error }
It is actually a fairly simple process to do this. Your CGI script must be able to perform two tasks:
Let's assume you're using the CGI::* modules. Here is how you would deal with sendmail:
One thing you should note is the "Reply-To:" header. Since the server is running as user "nobody", the mail headers might be messed up (especially when people are trying to reply to it). The "Reply-To:" field fixes that.$cgi_form = new CGI::Form; $from = $cgi_form->param('from'); $name = $cgi_form->param('name'); $to = $cgi_form->param('to'); $subject = $cgi_form->param('subject'); $message = $cgi_form->param('message'); open (SENDMAIL, "| /usr/bin/sendmail -t -n"); print SENDMAIL <<End_of_Mail; From: $from <$name> To: $to Reply-To: $from Subject: $subject $message End_of_Mail
There are a lot of mail gateways floating around that use mail in the following format:
open (MAIL, "| mail -s 'Subject' $to"); ^ | +-- Possible security hole!!!!
If you don't check the $to variable for shell metacharacters, you're in for a major headache! For example, if some malicious user entered the following:
; rm -fr / ;
You'll have a major problem on your hands.
Unfortunately, the mailto: command is not supported by all browsers. If you have this in your document, it is a limiting factor, as people who use browsers that do not support this, will not have the ability to send you mail.
Perl has been ported to all the platforms that are mentioned above. As a result, your PCP program should be reasonably portable. If you're are interfacing with various external programs on the UNIX side, then it probably will not be portable, but if you're just manipulating data, opening and reading files, etc., you should have no problem.
In a CGI environment, STDERR points to the server error log file. You can take this to your advantage by outputting debug messages, and then checking the log file later on.
Both STDIN and STDOUT point to the browser. In actuality, STDIN actualls points to the server which interprets the client (or browser's) request and information, and sends that to the script.
In order to catch errors, you can "dupe" STDERR to STDOUT early on in your script (after outputting the valid HTTP headers):
This redirects all of the error messages to STDOUT (i.e the browser).open (STDERR, ">&STDOUT");
Counter scripts tend to be very popular. The idea behind a counter is very simple:
Here is a simple counter script:
You can now use SSI (Server Side Includes) to display a counter in your HTML document:#!/usr/local/bin/perl $counter = "/home/shishir/counter.dat"; print "Content-type: text/plain", "\n\n"; open (FILE, $counter) || die "Cannot read from the counter file.\n"; flock (FILE, 2); $visitors = <FILE>; flock (FILE, 8); close (FILE); open (FILE, ">" . $counter) || die "Cannot write to counter file.\n"; flock (FILE, 2); print FILE $visitors; flock (FILE, 8); close (FILE);
You are visitor number:

Here is a simple regular expression that will strip HTML tags:
$line =~ s/<(([^ >]|\n)*)>//g;
Or you can "escape" certain characters in a HTML tag so that it can be displayed:
$line =~ s/<(([^>]|\n)*)>/<$1>/g;
For more information, see Tom's striphtml program, which is also included in his tour of perl5 regexps.
You can use the environment variable HTTP_USER_AGENT to determine the user's browser.
[ From WWW FAQ ]
Five important environment variables are available to your CGI script to help in identifying the end user.
This variable is set if the server has contacted an IDENTD server on the client machine. This is a slow operation, usually turned off in most servers, and there is no way to ensure that the client machine will respond honestly to the query, if it responds at all.
This variable will not identify the user specifically, but does provide information about the site the user has connected from, if the hostname was retrieved by the server. In the absence of any certainty regarding the user's precise identity, making decisions based on a list of trusted addresses is sometimes an adequate workaround. This variable is not set if the server failed to look up the host name or skipped the lookup in the interest of speed; see REMOTE_ADDR below. Also keep in mind that you may see all users of a particular proxy server listed under one hostname.
This variable will not identify the user specifically, but does provide information about the site the user has connected from. REMOTE_ADDR will contain the dotted-decimal IP address of the client. In the absence of any certainty regarding the user's precise identity, making decisions based on a list of trusted addresses is sometimes an adequate workaround. This variable is always set, unlike REMOTE_HOST, above. Also keep in mind that you may see all users of a particular proxy server listed under one address.
If you configure your server so that it recognizes that all files in a specific directory (i.e "cgi-bin"), or files with certain extensions (i.e ".pl", ".tcl", ".sh", etc) are CGI programs, then the server will execute these programs. There is no way for users to see the script itself.
On the other hand, if you allow people to look at your script (by placing it, for example, in the document root directory), it is not a security problem, in most cases, providing that there are no security holes in the program. If the program does contain security holes and you allow users to view the program, then they can and will exploit the problem.
No, your CGI scripts can access files outside the server and document root directories, unless the server is running in a chroot-ed environment.
No! The forms interface allows you to have a "password" field, but it should not be used for anything highly confidential. The main reason for this is that all form data (including "password" fields) gets sent from the browser to the Web server as plain text, and not as encrypted data.
If you want to solicit secure information, you need to use a secure server, such as Netscape's Commerce Server.
You can have your CGI script determine whether your script is being accessed by Netscape by using the environment variable HTTP_USER_AGENT. Here is an example:
$browser = $ENV{'HTTP_USER_AGENT'}; if ($browser =~ /Mozilla/) { # # Netscape # } else { # # Non Netscape # }
This has to do with the way the standard output is buffered. In order for the output to display in the correct order, you need to turn buffering off by using the $| variable:
$| = 1;
No, No. The concept of Java is totally different than that of CGI. CGI refers to server-side execution, while Java refers to client-side execution. There are certain things (like animations) which can be improved by using Java. However, you can continue to use Perl to develop server-side applications.
For more information, here are a few documents you can look at:
You can access the environment variables through the %ENV associative array. Here is a simple script that dumps out all of the environment variables (sorted):
#!/usr/local/bin/perl print "Content-type: text/plain", "\n\n"; foreach $key (sort keys %ENV) { print $key, " = ", $ENV{$key}, "\n"; } exit (0);
Unfortunately, not all browsers set the same environment variables. For example, HTTP_REFERER is not set by all browsers.
If you send a MIME content type of HTML, you will have to "escape" certain characters, such as "<", "&" and ">", or else the browser will think it is HTML.
You have to escape the characters by using the following construct:
&#ASCII Code;
Here is a simple script that you can run on the command-line that will give you the ASCII code for non alpha-numeric characters:
#!/usr/local/bin/perl print "Please enter a string: "; chop ($string = <STDIN>); $string =~ s/([^\w\s])/sprintf ("&#%d;", ord ($1))/ge; print "The escaped string is: $string\n"; exit (0);
This most likely is due to permission problems. Remember, your server is probably running as "nobody", "www", or a process with very minimal privileges. As a result, it will not be able to execute your script unless it has permissions to do so.
Again, this has to do with permissions! The server cannot write to a file in a certain directory if it does not have permissions to do so.
You should make it a point to check for error status from the open command:
print "Content-type: text/plain\n\n"; . . . open (FILE, ">" . "/some/dir/some.file") || print "Cannot write to the data file!"; . . .
You can use the CGI::MiniSvr module to keep state between multiple entry points.
Or you can create a series of dynamic documents that pass a unique session identification, either as a query, extra path name, or as a hidden field, to each other.
It's difficult to debug a CGI script. You can emulate a server by setting environment variables manually:
You can emulate a POST request by placing the data in a file and piping it to your program:setenv HTTP_USER_AGENT "Mozilla/2.0b6" (csh) or export HTTP_USER_AGENT = "Mozilla/2.0b6" (ksh, bash)
cat data.file | some_program.pl
You can use the CGI.pm (or the CGI::* modules) to debug your script. Say you have a simple script like the following, which prints out all the key/value pairs you pass it.
The script doesn't care whether you're passing the values as a GET, POST or ISINDEX query, or from the command line, standard input, or text file. For debugging purposes, let's pass some values through the command line:#!/usr/local/bin/perl5 use CGI; $cgi = new CGI; print $cgi->header; print $cgi->start_html("Simple CGI.pm Program"); print "
Simple CGI.pm Program
\n"; print "
"; print "Here is a list of the values you passed: "; print $cgi->dump; exit (0);
In the second example, you have to have quotes around the entire string, or else the shell will get confused when it sees the "&" character. Now, here is how you would debug from standard input:% simple.cgi first=shishir last=gundavaram document='CGI\ FAQ' or % simple.cgi "first=shishir&last=gundavaram&document='CGI\ FAQ'"
Of course, you can also use a file to store the form data, and then do input redirection, like so:% simple.cgi (waiting for standard input) first=shishir last=gundavaram document=CGI\ FAQ ^D
% simple.cgi < form.data
You can use also use CGI Lint -- will be released shortly -- which will do much of the same. It will also check for potential security problems, errors in open () and invalid HTTP headers.
You can call a CGI program by simply opening the URL to it:
http://some.machine/cgi-bin/your_program.pl
You can also have a link in a document, such as:

Click here to access my CGI program
The reason they call a form with nothing filled in is that they save the URL to the form, which they then call again, which is just an empty GET (and not a POST or a filled-out GET).
However, you can check the information from all the fields and return a "no response" if any of them are empty. Here is an example (assume the associative array %form contains your form information):
$error = 0; foreach $value (values %form) { $value =~ s/\s//g; $error = 1 unless ($value); } if ($error) { print "Content-type: text/plain\n"; print "Status: 204 No Response\n\n"; print "You should only see this message if your browser does"; print "not support the status code 204\n"; } else { # # Process Data Here # }
A CGI program can send specific response codes to the server, which in turn, it will send to the browser. For example, if you want a "No Response" (meaning that the browser will not load a new page), then you need to send a response code of 204 (see above).
print "Location: http://host/page.html\n"
work? Why does it only work the first time and get
the redirects wrong later?
A CGI program can only send one Location header. You also cannot send a MIME content type if you want the server to perform redirection. For example, this is not valid, though it may work with some servers:
#!/usr/local/bin/perl . . . print "Content-type: text/plain\n" print "Location: http://some.machine/some.doc\n\n"";
"Last updated: ..."
line at the bottom of all my HTML pages? Or can I only do that for
SSI pages? How do I get the date of the CGI script?
If you are dynamically creating documents using CGI, then you can insert a timestamp pretty easily. Here is an example (Perl 5 only).
or:$last_updated = localtime (time); print "Last updated: $last_updated\n";
or even:require "ctime.pl"; $last_updated = &ctime (time); print "Last updated: $last_updated\n";
You can accomplish this with SSI like this:chop ($date = `/usr/local/bin/date`); print "Last updated: $last_updated\n";
<--#echo var="LAST_MODIFIED"-->
Each language has its own advantages and disadvantages. I'm sure you've heard this many times: it depends on what you're trying to do. If you writing a CGI that's going to be accessed thousands of times in an hour, then you should write it in C or C++. If you are looking for a quick solution (as far as implementation), then Perl is the way to go!
You should generally avoid the shell for any type of CGI programming, just because of the potential for security problems.
The answer to this is: a CGI program is prone to security problems no matter what language it is written in!
Never expose any form data to the shell. All of the following are possible security holes:
open (COMMAND, "/usr/ucb/finger $form_user");
system ("/usr/ucb/finger $form_user");
@data = `usr/ucb/finger $form_user`;
However, the second construct can be made safer by passing the arguments as a list, rather than a string -- which the shell will mess with:
system ("/usr/ucb/finger", $form_user);
You should also look at:
http://bigidiot.abuse-me.com/perl.exe?foo.pl
is dangerous? How bad can it be?
Extremely dangerous! Just imagine what will happen if I do something like this:
http://bigidiot.abuse-me.com/cgi-bin/perl.exe?-e+'format:%20c'
Now, do you agree with me? The way to avoid these potential nightmares is to:
Now, here's an example. Assume your CGI script is called "sample.pl" and your batch script is called "simple.bat":
Now, you can can do the following:@echo off c:\dos_perl\perl.exe c:\netscape\ns-home\docs\cgi-bin\simple.pl
Click Here
@ans = `grep '$user_field' some.file`;
Yes! It's very dangerous! Imagine if $user_field contains something like the following:
; rm -fr / ;
A much safer way to accomplish the above is:
if (open (GREP, "-|")) { @ans = <GREP>; } else { exec ("/usr/local/bin/grep", $user_field, "some.file") || die "Error exec'ing command", "\n"; } close (GREP);
/$user_variable/
is a security hole in Perl 5?
No! It's not. It's a security hole if you evaluate the expression at runtime using the eval command. Something like can be dangerous:
foreach $regexp (@all_regexps) { eval "foreach (\@data) { push (\@matches, \$_) if m|$regexp|o; }"; }
This document, and all its parts, are Copyright (c) 1996, Shishir Gundavaram and Tom Christiansen. All rights reservered. Permisson to distribute this collection, in part or full, via electronic means (emailed, posted or archived) or printed copy are granted providing that no charges are involved, reasonable attempt is made to use the most current version, and all credits and copyright notices are retained. Requests for other distribution rights, including incorporation in commercial products, such as books, magazine articles, or CD-ROMs should be made to either of the authors.


This page tests changes to buttons, images, and other rich content inside of live regions. Note that these changes are NOT widely supported by all screen readers, so these should not be part of smoke tests.


+++ title = "Chicago dog" slug = "chicago-dog" date = 2007-10-18T11:00:00+10:00 tags = ["tasty", "hot-dogs", "crazy-consumptions"] locations = ["united-states/boston"] draft = false summary = """
If you ever find yourself in Salem, Massachusetts, don't miss going to the Boston Hot Dog Co. on the main street, and grabbing a "Chicago dog" for lunch. This has to be the best hot dog I've had in my life. Ever. Lovely grilled sausage, pickled cucumber, jalapeño chili peppers, lettuce, tomato (they say tom-AEY-to!), and American mustard, all on a chunky long roll. I devoured this dog, ears 'n' all (as my grandad would say). He had it coming.
""" +++If you ever find yourself in Salem, Massachusetts, don't miss going to the Boston Hot Dog Co. on the main street, and grabbing a "Chicago dog" for lunch. This has to be the best hot dog I've had in my life. Ever. Lovely grilled sausage, pickled cucumber, jalapeño chili peppers, lettuce, tomato (they say tom-AEY-to!), and American mustard, all on a chunky long roll. I devoured this dog, ears 'n' all (as my grandad would say). He had it coming.


1
a
import calendar
cal = calendar.TextCalendar()
cal.pryear(2012)
b
import calendar
cal = calendar.TextCalendar()
cal.setfirstweekday(3)
cal.pryear(2012)
c
import calendar
cal = calendar.TextCalendar()
cal.prmonth(1999,12)
d
d = calendar.LocaleTextCalendar(6, "SPANISH")
d.pryear(2012)
e
to deal with leap year
2
a
44
b
math.ceil
(x)¶
Return the ceiling of x, the smallest integer greater than or equal to x. If x is not a float, delegates to
x.ceil(), which should return an
Integral value.
math.floor(x)¶
Return the floor of x, the largest integer less than or equal to x. If x is not a float, delegates to x.floor(), which should return an Integral value.
c
begin with a number then get closer to it's square root
d
math.pi
math.e
3
deep copy copy all the objects
11
4
#mymodule1
myage = 16
year = 2016
#mymodule2
myage = 0
year = 1999
#namespace_test
import mymodule1
import mymodule2
print( (mymodule2.myage - mymodule1.myage) ==
(mymodule2.year - mymodule1.year) )
5
#mymodule1
myage = 16
year = 2016
print("My name is", __name__)
#mymodule2
myage = 0
year = 1999
print("My name is", __name__)
#namespace_test
import mymodule1
import mymodule2
print( (mymodule2.myage - mymodule1.myage) ==
(mymodule2.year - mymodule1.year) )
print("My name is", __name__)
if __name__ == "__main__":
print("This won't run if I'm imported.")
6
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
7
def myreplace(old, new, s):
a = s.split(old)
b = new.join(a)
return b
print(myreplace("a","b","banan is a good fra" ))
8
import string
def cleanword(s):
s_without_punct = ""
for letter in s:
if letter not in string.punctuation:
s_without_punct += letter
return s_without_punct
def has_dashdash(s):
a = s.find("--")
if a == -1:
return False
else:
return True
def extract_words(s):
b = s.split("--")
e = []
c = []
for i in b:
c = c + i.split()
for i in c:
i = cleanword(i)
i = i.lower()
e.append(i)
return e
def wordcount(w,s):
c = 0
for i in s:
if i== w:
c += 1
return c
def wordset(w):
w = list(set(w))
w.sort()
return w
def longestword(w):
a = 0
for i in w:
if len(i)> a:
a = len(i)
return a


bioRad provides standardized methods for extracting and reporting biological signals from weather radars. It includes functionality to inspect low-level radar data, process these data into meaningful biological information on animal speeds and directions at different altitudes in the atmosphere, visualize these biological extractions, and calculate further summary statistics.
To get started, see:
More vignettes:
Documentation for the latest development version can be found here.
bioRad depends on packages from both the CRAN and Bioconductor repositories. Enable both with:
setRepositories(ind = 1:2)
Required system libraries on Linux (Ubuntu)
The following system libraries are required before installing bioRad on Linux systems. In terminal, install these with:
You can install the released version of bioRad from CRAN with:
install.packages("bioRad")
Alternatively, you can install the latest development version from GitHub with:
# install.packages("devtools") devtools::install_github("adokter/bioRad")
Then load the package with:
library(bioRad) #> Welcome to bioRad version 0.5.2 #> Docker daemon running, Docker functionality enabled (vol2bird version 0.5.0, MistNet available)
You need to install Docker to:
calculate_vp()
.read_pvolfile()
. Docker is not required for reading ODIM radar data.nexrad_to_odim()
.calculate_vp()
or apply_mistnet()
Why? bioRad makes use of a C implementation of the vol2bird algorithm through Docker to do the above. All other bioRad functions will work without a Docker installation.
Installing Docker
Settings
> Shared drives
> Select the drive(s) where you will be processing radar files > Click Apply
.Preferences
> File sharing
> Add the drive(s) where you will be processing radar files > Click Apply & Restart
.check_docker()
.Known issues with Docker
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
, see this solution. Running sudo usermod -a -G docker $USER
in a terminal will fix this problem.bioRad can read weather radar data (= polar volumes) in the ODIM
format and formats supported by the RSL library, such as NEXRAD data. NEXRAD data (US) are available as open data and on AWS.
Here we read an example polar volume data file with read_pvolfile()
, extract the scan/sweep at elevation angle 3 with get_scan()
, project the data to a plan position indicator with project_as_ppi()
and plot the radial velocity of detected targets with plot()
:
library(tidyverse) # To pipe %>% the steps below system.file("extdata", "volume.h5", package = "bioRad") %>% read_pvolfile() %>% get_scan(3) %>% project_as_ppi() %>% plot(param = "VRADH") # VRADH = radial velocity in m/s
Radial velocities towards the radar are negative, while radial velocities away from the radar are positive, so in this plot there is movement from the top right to the bottom left.
Weather radar data can be processed into vertical profiles of biological targets using calculate_vp()
. This type of data is available as open data for over 100 European weather radars.
Once vertical profile data are loaded into bioRad, these can be bound into time series using bind_into_vpts()
. Here we read an example time series, project it on a regular time grid with regularize_vpts()
and plot it with plot()
:
example_vpts %>% regularize_vpts() %>% plot() #> projecting on 300 seconds interval grid...
The gray bars in the plot indicate gaps in the data.
The altitudes in the profile can be integrated with integrate_profile()
resulting in a dataframe with rows for datetimes and columns for quantities. Here we plot the quantity migration traffic rate (column mtr
) with plot()
:
my_vpi <- integrate_profile(example_vpts) plot(my_vpi, quantity = "mtr") # mtr = migration traffic rate
To know the total number of birds passing over the radar during the full time series, we use the last value of the cumulative migration traffic (column mt
):
my_vpi %>% pull(mt) %>% # Extract column mt as a vector last() #> [1] 173023.8
For more exercises, see this tutorial.
bioRad
in R doing citation("bioRad")
.