text:
package org.apache.harmony.tests.java.util;

import static com.google.j2objc.util.NativeTimeZoneTest.isNativeTimeZone;

import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

public class DateTest extends junit.framework.TestCase {

    /**
     * java.util.Date#Date()
     */
    public void test_Constructor() {
        // Test for method java.util.Date()
        GregorianCalendar gc = new GregorianCalendar(1998, Calendar.OCTOBER,
                13, 19, 9);
        long oldTime = gc.getTime().getTime();
        long now = new Date().getTime();
        assertTrue("Created incorrect date: " + oldTime + " now: " + now,
                oldTime < now);
    }

    /**
     * java.util.Date#Date(int, int, int)
     */
    public void test_ConstructorIII() {
        // Test for method java.util.Date(int, int, int)
        Date d1 = new Date(70, 0, 1); // the epoch + local time

        // the epoch + local time
        Date d2 = new Date(0 + d1.getTimezoneOffset() * 60 * 1000);

        assertTrue("Created incorrect date", d1.equals(d2));

        Date date = new Date(99, 5, 22);
        Calendar cal = new GregorianCalendar(1999, Calendar.JUNE, 22);
        assertTrue("Wrong time zone", date.equals(cal.getTime()));
    }

    /**
     * java.util.Date#Date(int, int, int, int, int)
     */
    public void test_ConstructorIIIII() {
        // Test for method java.util.Date(int, int, int, int, int)

        // the epoch + local time + (1 hour and 1 minute)
        Date d1 = new Date(70, 0, 1, 1, 1);

        // the epoch + local time + (1 hour and 1 minute)
        Date d2 = new Date(0 + d1.getTimezoneOffset() * 60 * 1000 + 60 * 60
                * 1000 + 60 * 1000);

        assertTrue("Created incorrect date", d1.equals(d2));
    }

    /**
     * java.util.Date#Date(int, int, int, int, int, int)
     */
    public void test_ConstructorIIIIII() {
        // Test for method java.util.Date(int, int, int, int, int, int)

        // the epoch + local time + (1 hour and 1 minute + 1 second)
        Date d1 = new Date(70, 0, 1, 1, 1, 1);

        // the epoch + local time + (1 hour and 1 minute + 1 second)
        Date d2 = new Date(0 + d1.getTimezoneOffset() * 60 * 1000 + 60 * 60
                * 1000 + 60 * 1000 + 1000);

        assertTrue("Created incorrect date", d1.equals(d2));
    }

    /**
     * java.util.Date#Date(java.lang.String)
     */
    public void test_ConstructorLjava_lang_String() {
        // Test for method java.util.Date(java.lang.String)
        Date d1 = new Date("January 1, 1970, 00:00:00 GMT"); // the epoch
        Date d2 = new Date(0); // the epoch
        assertTrue("Created incorrect date", d1.equals(d2));

        try {
            // Regression for HARMONY-238
            new Date(null);
            fail("Constructor Date((String)null) should "
                    + "throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }
    }

    /**
     * java.util.Date#after(java.util.Date)
     */
    public void test_afterLjava_util_Date() {
        // Test for method boolean java.util.Date.after(java.util.Date)
        Date d1 = new Date(0);
        Date d2 = new Date(1900000);
        assertTrue("Older was returned as newer", d2.after(d1));
        assertTrue("Newer was returned as older", !d1.after(d2));

        try {
            d1.after(null);
            fail("NullPointerException expected");
        } catch (NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Date#before(java.util.Date)
     */
    public void test_beforeLjava_util_Date() {
        // Test for method boolean java.util.Date.before(java.util.Date)
        Date d1 = new Date(0);
        Date d2 = new Date(1900000);
        assertTrue("Older was returned as newer", !d2.before(d1));
        assertTrue("Newer was returned as older", d1.before(d2));

        try {
            d1.before(null);
            fail("NullPointerException expected");
        } catch (NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Date#clone()
     */
    public void test_clone() {
        // Test for method java.lang.Object java.util.Date.clone()
        Date d1 = new Date(100000);
        Date d2 = (Date) d1.clone();
        assertTrue(
                "Cloning date results in same reference--new date is equivalent",
                d1 != d2);
        assertTrue("Cloning date results unequal date", d1.equals(d2));
    }

    /**
     * java.util.Date#compareTo(java.util.Date)
     */
    public void test_compareToLjava_util_Date() {
        // Test for method int java.util.Date.compareTo(java.util.Date)
        final int someNumber = 10000;
        Date d1 = new Date(someNumber);
        Date d2 = new Date(someNumber);
        Date d3 = new Date(someNumber + 1);
        Date d4 = new Date(someNumber - 1);
        assertEquals("Comparing a date to itself did not answer zero", 0, d1
                .compareTo(d1));
        assertEquals("Comparing equal dates did not answer zero", 0, d1
                .compareTo(d2));
        assertEquals("date1.compareTo(date2), where date1 > date2, did not result in 1",
                1, d1.compareTo(d4));
        assertEquals("date1.compareTo(date2), where date1 < date2, did not result in -1",
                -1, d1.compareTo(d3));

        try {
            d1.compareTo(null);
            fail("NullPointerException expected");
        } catch (NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Date#equals(java.lang.Object)
     */
    public void test_equalsLjava_lang_Object() {
        // Test for method boolean java.util.Date.equals(java.lang.Object)
        Date d1 = new Date(0);
        Date d2 = new Date(1900000);
        Date d3 = new Date(1900000);
        assertTrue("Equality test failed", d2.equals(d3));
        assertTrue("Equality test failed", !d1.equals(d2));
    }

    /**
     * java.util.Date#getDate()
     */
    public void test_getDate() {
        // Test for method int java.util.Date.getDate()
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        assertEquals("Returned incorrect date", 13, d.getDate());
    }

    /**
     * java.util.Date#getDay()
     */
    public void test_getDay() {
        // Test for method int java.util.Date.getDay()
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        assertEquals("Returned incorrect day", 2, d.getDay());
    }

    /**
     * java.util.Date#getHours()
     */
    public void test_getHours() {
        // Test for method int java.util.Date.getHours()
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        assertEquals("Returned incorrect hours", 19, d.getHours());
    }

    /**
     * java.util.Date#getMinutes()
     */
    public void test_getMinutes() {
        // Test for method int java.util.Date.getMinutes()
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        assertEquals("Returned incorrect minutes", 9, d.getMinutes());
    }

    /**
     * java.util.Date#getMonth()
     */
    public void test_getMonth() {
        // Test for method int java.util.Date.getMonth()
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        assertEquals("Returned incorrect month", 9, d.getMonth());
    }

    /**
     * java.util.Date#getSeconds()
     */
    public void test_getSeconds() {
        // Test for method int java.util.Date.getSeconds()
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        assertEquals("Returned incorrect seconds", 0, d.getSeconds());
    }

    /**
     * java.util.Date#getTime()
     */
    public void test_getTime() {
        // Test for method long java.util.Date.getTime()
        Date d1 = new Date(0);
        Date d2 = new Date(1900000);
        assertEquals("Returned incorrect time", 1900000, d2.getTime());
        assertEquals("Returned incorrect time", 0, d1.getTime());
    }

    /**
     * java.util.Date#getTimezoneOffset()
     */
    public void test_getTimezoneOffset() {
        // Test for method int java.util.Date.getTimezoneOffset()
        assertTrue("Used to test", true);
    }

    /**
     * java.util.Date#getYear()
     */
    public void test_getYear() {
        // Test for method int java.util.Date.getYear()
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        assertEquals("Returned incorrect year", 98, d.getYear());
    }

    /**
     * java.util.Date#hashCode()
     */
    public void test_hashCode() {
        // Test for method int java.util.Date.hashCode()
        Date d1 = new Date(0);
        Date d2 = new Date(1900000);
        assertEquals("Returned incorrect hash", 1900000, d2.hashCode());
        assertEquals("Returned incorrect hash", 0, d1.hashCode());
    }

    /**
     * java.util.Date#parse(java.lang.String)
     */
    public void test_parseLjava_lang_String() {
        // Test for method long java.util.Date.parse(java.lang.String)
        Date d = new Date(Date.parse("13 October 1998"));
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(d);
        assertEquals("Parsed incorrect month", 9, cal.get(Calendar.MONTH));
        assertEquals("Parsed incorrect year", 1998, cal.get(Calendar.YEAR));
        assertEquals("Parsed incorrect date", 13, cal.get(Calendar.DATE));

        d = new Date(Date.parse("Jan-12 1999"));
        assertTrue("Wrong parsed date 1", d.equals(new GregorianCalendar(1999,
                0, 12).getTime()));
        d = new Date(Date.parse("Jan12-1999"));
        assertTrue("Wrong parsed date 2", d.equals(new GregorianCalendar(1999,
                0, 12).getTime()));
        d = new Date(Date.parse("Jan12 69-1"));
        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
        cal.clear();
        cal.set(1969, Calendar.JANUARY, 12, 1, 0);
        assertTrue("Wrong parsed date 3", d.equals(cal.getTime()));
        d = new Date(Date.parse("6:45:13 3/2/1200 MST"));
        cal.setTimeZone(TimeZone.getTimeZone("MST"));
        cal.clear();
        cal.set(1200, 2, 2, 6, 45, 13);
        assertTrue("Wrong parsed date 4", d.equals(cal.getTime()));
        d = new Date(Date.parse("Mon, 22 Nov 1999 12:52:06 GMT"));
        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
        cal.clear();
        cal.set(1999, Calendar.NOVEMBER, 22, 12, 52, 06);
        assertTrue("Wrong parsed date 5", d.equals(cal.getTime()));

        try {
            // Regression for HARMONY-259
            Date.parse(null);
            fail("Date.parse(null) should throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected
        }

        // Regression for HARMONY-102
        assertEquals("Assert 0: parse failure",
                -5400000, Date.parse("Sat, 1 Jan 1970 +0130 00:00:00"));
        assertEquals("Assert 1: parse failure",
                858600000, Date.parse("00:00:00 GMT +0130 Sat, 11 Jan 1970"));
    }

    /**
     * java.util.Date#setDate(int)
     */
    public void test_setDateI() {
        // Test for method void java.util.Date.setDate(int)
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        d.setDate(23);
        assertEquals("Set incorrect date", 23, d.getDate());
    }

    /**
     * java.util.Date#setHours(int)
     */
    public void test_setHoursI() {
        // Test for method void java.util.Date.setHours(int)
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        d.setHours(23);
        assertEquals("Set incorrect hours", 23, d.getHours());
    }

    /**
     * java.util.Date#setMinutes(int)
     */
    public void test_setMinutesI() {
        // Test for method void java.util.Date.setMinutes(int)
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        d.setMinutes(45);
        assertEquals("Set incorrect mins", 45, d.getMinutes());
    }

    /**
     * java.util.Date#setMonth(int)
     */
    public void test_setMonthI() {
        // Test for method void java.util.Date.setMonth(int)
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        d.setMonth(0);
        assertEquals("Set incorrect month", 0, d.getMonth());
    }

    /**
     * java.util.Date#setSeconds(int)
     */
    public void test_setSecondsI() {
        // Test for method void java.util.Date.setSeconds(int)
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        d.setSeconds(13);
        assertEquals("Set incorrect seconds", 13, d.getSeconds());
    }

    /**
     * java.util.Date#setTime(long)
     */
    public void test_setTimeJ() {
        // Test for method void java.util.Date.setTime(long)
        Date d1 = new Date(0);
        Date d2 = new Date(1900000);
        d1.setTime(900);
        d2.setTime(890000);
        assertEquals("Returned incorrect time", 890000, d2.getTime());
        assertEquals("Returned incorrect time", 900, d1.getTime());
    }

    /**
     * java.util.Date#setYear(int)
     */
    public void test_setYearI() {
        // Test for method void java.util.Date.setYear(int)
        Date d = new GregorianCalendar(1998, Calendar.OCTOBER, 13, 19, 9)
                .getTime();
        d.setYear(8);
        assertEquals("Set incorrect year", 8, d.getYear());
    }

    /**
     * java.util.Date#toGMTString()
     */
    public void test_toGMTString() {
        // Test for method java.lang.String java.util.Date.toGMTString()
        assertEquals("Did not convert epoch to GMT string correctly", "1 Jan 1970 00:00:00 GMT", new Date(0)
                .toGMTString());
        assertEquals("Did not convert epoch + 1yr to GMT string correctly",
                "1 Jan 1971 00:00:00 GMT", new Date((long) 365 * 24 * 60 * 60 * 1000).toGMTString()
        );
    }

    /**
     * java.util.Date#toString()
     */
    public void test_toString() {
        // Test for method java.lang.String java.util.Date.toString()
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DATE, 1);
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.YEAR, 1970);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date d = cal.getTime();
        String result = d.toString();
        assertTrue("Incorrect result: " + d, result
                .startsWith("Thu Jan 01 00:00:00")
                && result.endsWith("1970"));

        TimeZone tz = TimeZone.getDefault();
        TimeZone.setDefault(TimeZone.getTimeZone("GMT-5"));
        try {
            Date d1 = new Date(0);
            String tzShortFormat = isNativeTimeZone("GMT-5") ? "GMT-5" : "GMT-05:00";
            assertTrue("Returned incorrect string: " + d1, d1.toString()
                    .equals("Wed Dec 31 19:00:00 " + tzShortFormat + " 1969"));
        } finally {
            TimeZone.setDefault(tz);
        }

        // Test for HARMONY-5468
        TimeZone.setDefault(TimeZone.getTimeZone("MST"));
        Date d2 = new Date(108, 7, 27);
        assertTrue("Returned incorrect string: " + d2, d2.toString()
                .startsWith("Wed Aug 27 00:00:00")
                && d2.toString().endsWith("2008"));
    }

    /**
     * java.util.Date#UTC(int, int, int, int, int, int)
     */
    public void test_UTCIIIIII() {
        // Test for method long java.util.Date.UTC(int, int, int, int, int, int)
        assertTrue("Returned incorrect UTC value for epoch", Date.UTC(70, 0, 1,
                0, 0, 0) == (long) 0);
        assertTrue("Returned incorrect UTC value for epoch +1yr", Date.UTC(71,
                0, 1, 0, 0, 0) == (long) 365 * 24 * 60 * 60 * 1000);
    }
    /**
     * java.util.Date#toLocaleString() Test for method java.lang.String
     *        java.util.Date.toGMTString()
     */
    public void test_toLocaleString() {
        Locale loc = Locale.getDefault();
        Locale.setDefault(Locale.US);
        TimeZone tz = TimeZone.getDefault();
        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
        // This test assumes a default DateFormat.is24Hour setting.
        DateFormat.is24Hour = null;
        try {
            assertEquals("Did not convert epoch to GMT string correctly", "Jan 1, 1970 12:00:00 AM",
                    new Date(0).toLocaleString());
            assertEquals("Did not convert epoch + 1yr to GMT string correctly",
                    "Jan 1, 1971 12:00:00 AM",
                    new Date((long)365 * 24 * 60 * 60 * 1000).toLocaleString());
        } finally {
            Locale.setDefault(loc);
            TimeZone.setDefault(tz);
        }
    }

    static TimeZone defaultTimeZone = TimeZone.getDefault();

    /**
     * Sets up the fixture, for example, open a network connection. This method
     * is called before a test is executed.
     */
    protected void setUp() {
    }

    /**
     * Tears down the fixture, for example, close a network connection. This
     * method is called after a test is executed.
     */
    protected void tearDown() {
        TimeZone.setDefault(defaultTimeZone);
    }
}


text:
#include "Benchmark.h"
#include "SkBlurImageFilter.h"
#include "SkCanvas.h"
#include "SkMergeImageFilter.h"

enum { kNumInputs = 5 };

// Exercise a blur filter connected to 5 inputs of the same merge filter.
// This bench shows an improvement in performance once cacheing of re-used
// nodes is implemented, since the DAG is no longer flattened to a tree.

class ImageFilterDAGBench : public Benchmark {
public:
    ImageFilterDAGBench() {}

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return "image_filter_dag";
    }

    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        for (int j = 0; j < loops; j++) {
            SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(20.0f, 20.0f));
            SkImageFilter* inputs[kNumInputs];
            for (int i = 0; i < kNumInputs; ++i) {
                inputs[i] = blur.get();
            }
            SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(inputs, kNumInputs));
            SkPaint paint;
            paint.setImageFilter(merge);
            SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400));
            canvas->drawRect(rect, paint);
        }
    }

private:
    typedef Benchmark INHERITED;
};

DEF_BENCH(return new ImageFilterDAGBench;)

redpajama_set_name: RedPajamaGithub


text:
(function() {
    'use strict';

    var module = angular.module('chat.ui.tickets', ['chat.ui.tickets.compose']);
    var TicketsController = function($scope, $http, $modalInstance, $modal) {
        makeClosable($scope, $modalInstance);

        $scope.entries = [];
        $scope.status = null;
        $scope.response = null;

        var loadData = function() {
            $scope.entries.length = 0;
            $http({method: 'GET', url: '/rest/userTicket'})
                .success(function (d) {
                    $scope.entries = d;
                })
                .error(function (data) {
                    alert(data);
                });
        };

        $scope.compose = function() {
            $modal.open({
                templateUrl: 'chat/ui/tickets/compose.html',
                controller: 'ComposeTicketController',
                size: 'sm'
            }).result.then(function() {
                loadData();
            });
        };

        loadData();
    };

    module.controller('TicketsController', ['$scope', '$http', '$modalInstance', '$modal', TicketsController])
})();


text:
{-# LANGUAGE CPP #-}

#if __GLASGOW_HASKELL__ >= 720
{-# LANGUAGE Safe #-}
#endif

module Data.IntervalSet
       (
         -- * Types
         IntSet(..), Key

         -- * Query
         -- ** Cardinality
       , SB.null
       , size

         -- ** Membership
       , member, notMember

         -- ** Inclusion
       , isSubsetOf, isSupersetOf
--       , isProperSubsetOf, isProperSupersetOf

         -- * Construction
       , empty
       , singleton
       , interval
{-
       , naturals
       , negatives
       , universe
-}
         -- * Modification
       , insert
       , delete

         -- * Map Fold Filter
       , SB.map
       , SB.foldr
       , SB.filter

         -- * Splits
       , split, splitGT, splitLT
       , partition

         -- * Min/Max
       , findMin, findMax

         -- * Combine
       , union, unions
       , intersection, intersections
       , difference, symDiff

         -- ** Monoids
       , Union, Intersection, Difference

         -- * Conversion
         -- *** Arbitary
       , elems
       , toList, fromList

         -- *** Ordered
       , toAscList, toDescList
       , fromAscList

#if defined (TESTING)
         -- * Debug
       , isValid, splitFin
#endif
       ) where

import Data.IntervalSet.Internal as SB


text:
package com.pushsignal.push;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.pushsignal.http.HttpExecutor;
import com.pushsignal.http.HttpResponse;

@Service(value="PushClientGCM")
public class PushClientGcmImpl implements PushClient {

	private static final Logger LOG = LoggerFactory.getLogger(PushClientGcmImpl.class);

	private static final String GCM_API_KEY = "AIzaSyBDyyuZGPPww5j08ikk6RZwaUeVX_APboI";
	private static final String GCM_POST_URL = "https://android.googleapis.com/gcm/send";

	private int collapseKey;

	public PushClientGcmImpl() {
		collapseKey = new Random().nextInt();
	}

	public synchronized void sendMessage(final String deviceId, final String registrationId, final String message) {
		collapseKey++;
		final Map<String, String> params = new HashMap<String, String>();
		params.put("registration_id", registrationId);
		params.put("collapse_key", "PushSignal" + collapseKey);
		params.put("data.message", message);
		final Map<String, String> requestProperties = new HashMap<String, String>();
		requestProperties.put("Authorization", "key=" + GCM_API_KEY);

		final HttpResponse httpResponse = HttpExecutor.executePost(GCM_POST_URL, requestProperties, params);

		if (httpResponse.getStatusCode() == HttpServletResponse.SC_OK) {
			// Do nothing - everything worked
			LOG.debug(StringUtils.join(httpResponse.getResponseLines(), "\n"));
		} else {
			LOG.error("Error while sending GCM message: HttpStatusCode " + httpResponse.getStatusCode());
		}
	}
}


text:
if [[ -e /.firstrun ]]; then
    /scripts/first_run.sh
fi

# Start MongoDB
echo "Starting MongoDB..."
/usr/bin/mongod --dbpath /data --auth $@


text:
#include "vrtdataset.h"
#include "cpl_minixml.h"
#include "cpl_string.h"

CPL_CVSID("$Id: vrtsourcedrasterband.cpp 29161 2015-05-06 10:18:19Z rouault $");

/************************************************************************/
/* ==================================================================== */
/*                          VRTSourcedRasterBand                        */
/* ==================================================================== */
/************************************************************************/

/************************************************************************/
/*                        VRTSourcedRasterBand()                        */
/************************************************************************/

VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand )

{
    Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );

    this->poDS = poDS;
    this->nBand = nBand;
}

/************************************************************************/
/*                        VRTSourcedRasterBand()                        */
/************************************************************************/

VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType,
                                            int nXSize, int nYSize )

{
    Initialize( nXSize, nYSize );

    eDataType = eType;
}

/************************************************************************/
/*                        VRTSourcedRasterBand()                        */
/************************************************************************/

VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand,
                                            GDALDataType eType,
                                            int nXSize, int nYSize )

{
    Initialize( nXSize, nYSize );

    this->poDS = poDS;
    this->nBand = nBand;

    eDataType = eType;
}

/************************************************************************/
/*                             Initialize()                             */
/************************************************************************/

void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )

{
    VRTRasterBand::Initialize( nXSize, nYSize );

    nSources = 0;
    papoSources = NULL;
    bEqualAreas = FALSE;
    nRecursionCounter = 0;
    papszSourceList = NULL;
}

/************************************************************************/
/*                       ~VRTSourcedRasterBand()                        */
/************************************************************************/

VRTSourcedRasterBand::~VRTSourcedRasterBand()

{
    CloseDependentDatasets();
    CSLDestroy(papszSourceList);
}

/************************************************************************/
/*                             IRasterIO()                              */
/************************************************************************/

CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
                                 GDALDataType eBufType,
                                 GSpacing nPixelSpace,
                                 GSpacing nLineSpace,
                                 GDALRasterIOExtraArg* psExtraArg )

{
    int         iSource;
    CPLErr      eErr = CE_None;

    if( eRWFlag == GF_Write )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Writing through VRTSourcedRasterBand is not supported." );
        return CE_Failure;
    }

    /* When using GDALProxyPoolDataset for sources, the recusion will not be */
    /* detected at VRT opening but when doing RasterIO. As the proxy pool will */
    /* return the already opened dataset, we can just test a member variable. */
    /* We allow 1, since IRasterIO() can be called from ComputeStatistics(), which */
    /* itselfs increments the recursion counter */
    if ( nRecursionCounter > 1 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "VRTSourcedRasterBand::IRasterIO() called recursively on the same band. "
                  "It looks like the VRT is referencing itself." );
        return CE_Failure;
    }

/* ==================================================================== */
/*      Do we have overviews that would be appropriate to satisfy       */
/*      this request?                                                   */
/* ==================================================================== */
    if( (nBufXSize < nXSize || nBufYSize < nYSize)
        && GetOverviewCount() > 0 )
    {
        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                              pData, nBufXSize, nBufYSize,
                              eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
            return CE_None;
    }

/* -------------------------------------------------------------------- */
/*      Initialize the buffer to some background value. Use the         */
/*      nodata value if available.                                      */
/* -------------------------------------------------------------------- */
    if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
         (!bNoDataValueSet || (!CPLIsNan(dfNoDataValue) && dfNoDataValue == 0)) )
    {
        if (nLineSpace == nBufXSize * nPixelSpace)
        {
             memset( pData, 0, (GIntBig)nBufYSize * nLineSpace );
        }
        else
        {
            int    iLine;
            for( iLine = 0; iLine < nBufYSize; iLine++ )
            {
                memset( ((GByte*)pData) + (GIntBig)iLine * nLineSpace, 0, nBufXSize * nPixelSpace );
            }
        }
    }
    else if ( !bEqualAreas || bNoDataValueSet )
    {
        double dfWriteValue = 0.0;
        int    iLine;

        if( bNoDataValueSet )
            dfWriteValue = dfNoDataValue;

        for( iLine = 0; iLine < nBufYSize; iLine++ )
        {
            GDALCopyWords( &dfWriteValue, GDT_Float64, 0,
                           ((GByte *)pData) + (GIntBig)nLineSpace * iLine,
                           eBufType, nPixelSpace, nBufXSize );
        }
    }

    nRecursionCounter ++;

    GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
    void             *pProgressDataGlobal = psExtraArg->pProgressData;

/* -------------------------------------------------------------------- */
/*      Overlay each source in turn over top this.                      */
/* -------------------------------------------------------------------- */
    for( iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
    {
        psExtraArg->pfnProgress = GDALScaledProgress;
        psExtraArg->pProgressData =
                GDALCreateScaledProgress( 1.0 * iSource / nSources,
                                        1.0 * (iSource + 1) / nSources,
                                        pfnProgressGlobal,
                                        pProgressDataGlobal );
        if( psExtraArg->pProgressData == NULL )
            psExtraArg->pfnProgress = NULL;

        eErr =
            papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize,
                                            pData, nBufXSize, nBufYSize,
                                            eBufType, nPixelSpace, nLineSpace,
                                            psExtraArg);

        GDALDestroyScaledProgress( psExtraArg->pProgressData );
    }

    psExtraArg->pfnProgress = pfnProgressGlobal;
    psExtraArg->pProgressData = pProgressDataGlobal;

    nRecursionCounter --;

    return eErr;
}

/************************************************************************/
/*                             IReadBlock()                             */
/************************************************************************/

CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )

{
    int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
    int nReadXSize, nReadYSize;

    if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
        nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
    else
        nReadXSize = nBlockXSize;

    if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
        nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
    else
        nReadYSize = nBlockYSize;

    GDALRasterIOExtraArg sExtraArg;
    INIT_RASTERIO_EXTRA_ARG(sExtraArg);

    return IRasterIO( GF_Read,
                      nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
                      nReadXSize, nReadYSize,
                      pImage, nReadXSize, nReadYSize, eDataType,
                      nPixelSize, nPixelSize * nBlockXSize, &sExtraArg );
}

/************************************************************************/
/*                    CanUseSourcesMinMaxImplementations()              */
/************************************************************************/

int VRTSourcedRasterBand::CanUseSourcesMinMaxImplementations()
{
    const char* pszUseSources = CPLGetConfigOption("VRT_MIN_MAX_FROM_SOURCES", NULL);
    if( pszUseSources )
        return CSLTestBoolean(pszUseSources);

    // Use heuristics to determine if we are going to use the source GetMinimum()
    // or GetMaximum() implementation: all the sources must be "simple" sources
    // with a dataset description that match a "regular" file on the filesystem,
    // whose open time and GetMinimum()/GetMaximum() implementations we hope to
    // be fast enough.
    // In case of doubt return FALSE
    for( int iSource = 0; iSource < nSources; iSource++ )
    {
        if( !(papoSources[iSource]->IsSimpleSource()) )
            return FALSE;
        VRTSimpleSource* poSimpleSource = (VRTSimpleSource*) papoSources[iSource];
        GDALRasterBand* poBand = poSimpleSource->GetBand();
        if( poBand == NULL )
            return FALSE;
        if( poBand->GetDataset() == NULL )
            return FALSE;
        const char* pszFilename = poBand->GetDataset()->GetDescription();
        if( pszFilename == NULL )
            return FALSE;
        /* /vsimem/ should be fast */
        if( strncmp(pszFilename, "/vsimem/", 8) == 0 )
            continue;
        /* but not other /vsi filesystems */
        if( strncmp(pszFilename, "/vsi", 4) == 0 )
            return FALSE;
        int i = 0;
        char ch;
        /* We will assume that filenames that are only with ascii characters */
        /* are real filenames and so we will not try to 'stat' them */
        for( i = 0; (ch = pszFilename[i]) != '\0'; i++ )
        {
            if( !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
                  (ch >= '0' && ch <= '9') || ch == ':' || ch == '/' || ch == '\\' ||
                  ch == ' ' || ch == '.') )
                break;
        }
        if( ch != '\0' )
        {
            /* Otherwise do a real filesystem check */
            VSIStatBuf sStat;
            if( VSIStat(pszFilename, &sStat) != 0 )
                return FALSE;
        }
    }
    return TRUE;
}

/************************************************************************/
/*                             GetMinimum()                             */
/************************************************************************/

double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
{
    const char *pszValue = NULL;

    if( !CanUseSourcesMinMaxImplementations() )
        return GDALRasterBand::GetMinimum(pbSuccess);

    if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
    {
        if( pbSuccess != NULL )
            *pbSuccess = TRUE;

        return CPLAtofM(pszValue);
    }

    if ( nRecursionCounter > 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "VRTSourcedRasterBand::GetMinimum() called recursively on the same band. "
                  "It looks like the VRT is referencing itself." );
        if( pbSuccess != NULL )
            *pbSuccess = FALSE;
        return 0.0;
    }
    nRecursionCounter ++;

    double dfMin = 0;
    for( int iSource = 0; iSource < nSources; iSource++ )
    {
        int bSuccess = FALSE;
        double dfSourceMin = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(), &bSuccess);
        if (!bSuccess)
        {
            dfMin = GDALRasterBand::GetMinimum(pbSuccess);
            nRecursionCounter --;
            return dfMin;
        }

        if (iSource == 0 || dfSourceMin < dfMin)
            dfMin = dfSourceMin;
    }

    nRecursionCounter --;

    if( pbSuccess != NULL )
        *pbSuccess = TRUE;

    return dfMin;
}

/************************************************************************/
/*                             GetMaximum()                             */
/************************************************************************/

double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
{
    const char *pszValue = NULL;

    if( !CanUseSourcesMinMaxImplementations() )
        return GDALRasterBand::GetMaximum(pbSuccess);

    if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
    {
        if( pbSuccess != NULL )
            *pbSuccess = TRUE;

        return CPLAtofM(pszValue);
    }

    if ( nRecursionCounter > 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "VRTSourcedRasterBand::GetMaximum() called recursively on the same band. "
                  "It looks like the VRT is referencing itself." );
        if( pbSuccess != NULL )
            *pbSuccess = FALSE;
        return 0.0;
    }
    nRecursionCounter ++;

    double dfMax = 0;
    for( int iSource = 0; iSource < nSources; iSource++ )
    {
        int bSuccess = FALSE;
        double dfSourceMax = papoSources[iSource]->GetMaximum(GetXSize(), GetYSize(), &bSuccess);
        if (!bSuccess)
        {
            dfMax = GDALRasterBand::GetMaximum(pbSuccess);
            nRecursionCounter --;
            return dfMax;
        }

        if (iSource == 0 || dfSourceMax > dfMax)
            dfMax = dfSourceMax;
    }

    nRecursionCounter --;

    if( pbSuccess != NULL )
        *pbSuccess = TRUE;

    return dfMax;
}

/************************************************************************/
/*                       ComputeRasterMinMax()                          */
/************************************************************************/

CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinMax )
{
    double  dfMin = 0.0;
    double  dfMax = 0.0;

/* -------------------------------------------------------------------- */
/*      Does the driver already know the min/max?                       */
/* -------------------------------------------------------------------- */
    if( bApproxOK )
    {
        int          bSuccessMin, bSuccessMax;

        dfMin = GetMinimum( &bSuccessMin );
        dfMax = GetMaximum( &bSuccessMax );

        if( bSuccessMin && bSuccessMax )
        {
            adfMinMax[0] = dfMin;
            adfMinMax[1] = dfMax;
            return CE_None;
        }
    }

/* -------------------------------------------------------------------- */
/*      If we have overview bands, use them for min/max.                */
/* -------------------------------------------------------------------- */
    if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    {
        GDALRasterBand *poBand;

        poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );

        if ( poBand != this )
            return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
    }

/* -------------------------------------------------------------------- */
/*      Try with source bands.                                          */
/* -------------------------------------------------------------------- */
    if ( nRecursionCounter > 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "VRTSourcedRasterBand::ComputeRasterMinMax() called recursively on the same band. "
                  "It looks like the VRT is referencing itself." );
        return CE_Failure;
    }
    nRecursionCounter ++;

    adfMinMax[0] = 0.0;
    adfMinMax[1] = 0.0;
    for( int iSource = 0; iSource < nSources; iSource++ )
    {
        double adfSourceMinMax[2];
        CPLErr eErr = papoSources[iSource]->ComputeRasterMinMax(GetXSize(), GetYSize(), bApproxOK, adfSourceMinMax);
        if (eErr != CE_None)
        {
            eErr = GDALRasterBand::ComputeRasterMinMax(bApproxOK, adfMinMax);
            nRecursionCounter --;
            return eErr;
        }

        if (iSource == 0 || adfSourceMinMax[0] < adfMinMax[0])
            adfMinMax[0] = adfSourceMinMax[0];
        if (iSource == 0 || adfSourceMinMax[1] > adfMinMax[1])
            adfMinMax[1] = adfSourceMinMax[1];
    }

    nRecursionCounter --;

    return CE_None;
}

/************************************************************************/
/*                         ComputeStatistics()                          */
/************************************************************************/

CPLErr
VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
                                   double *pdfMin, double *pdfMax,
                                   double *pdfMean, double *pdfStdDev,
                                   GDALProgressFunc pfnProgress,
                                   void *pProgressData )

{
    if( nSources != 1 || bNoDataValueSet )
        return GDALRasterBand::ComputeStatistics(  bApproxOK,
                                              pdfMin, pdfMax,
                                              pdfMean, pdfStdDev,
                                              pfnProgress, pProgressData );

    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

/* -------------------------------------------------------------------- */
/*      If we have overview bands, use them for statistics.             */
/* -------------------------------------------------------------------- */
    if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    {
        GDALRasterBand *poBand;

        poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );

        if( poBand != this )
            return poBand->ComputeStatistics( FALSE,
                                              pdfMin, pdfMax,
                                              pdfMean, pdfStdDev,
                                              pfnProgress, pProgressData );
    }

/* -------------------------------------------------------------------- */
/*      Try with source bands.                                          */
/* -------------------------------------------------------------------- */
    if ( nRecursionCounter > 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "VRTSourcedRasterBand::ComputeStatistics() called recursively on the same band. "
                  "It looks like the VRT is referencing itself." );
        return CE_Failure;
    }
    nRecursionCounter ++;

    double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;

    CPLErr eErr = papoSources[0]->ComputeStatistics(GetXSize(), GetYSize(), bApproxOK,
                                                    &dfMin, &dfMax,
                                                    &dfMean, &dfStdDev,
                                                    pfnProgress, pProgressData);
    if (eErr != CE_None)
    {
        eErr = GDALRasterBand::ComputeStatistics(bApproxOK,
                                                 pdfMin, pdfMax,
                                                 pdfMean, pdfStdDev,
                                                 pfnProgress, pProgressData);
        nRecursionCounter --;
        return eErr;
    }

    nRecursionCounter --;

    SetStatistics( dfMin, dfMax, dfMean, dfStdDev );

/* -------------------------------------------------------------------- */
/*      Record results.                                                 */
/* -------------------------------------------------------------------- */
    if( pdfMin != NULL )
        *pdfMin = dfMin;
    if( pdfMax != NULL )
        *pdfMax = dfMax;

    if( pdfMean != NULL )
        *pdfMean = dfMean;

    if( pdfStdDev != NULL )
        *pdfStdDev = dfStdDev;

    return CE_None;
}

/************************************************************************/
/*                            GetHistogram()                            */
/************************************************************************/

CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
                                     int nBuckets, GUIntBig *panHistogram,
                                     int bIncludeOutOfRange, int bApproxOK,
                                     GDALProgressFunc pfnProgress,
                                     void *pProgressData )

{
    if( nSources != 1 )
        return GDALRasterBand::GetHistogram( dfMin, dfMax,
                                             nBuckets, panHistogram,
                                             bIncludeOutOfRange, bApproxOK,
                                             pfnProgress, pProgressData );

    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

/* -------------------------------------------------------------------- */
/*      If we have overviews, use them for the histogram.               */
/* -------------------------------------------------------------------- */
    if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
    {
        // FIXME: should we use the most reduced overview here or use some
        // minimum number of samples like GDALRasterBand::ComputeStatistics()
        // does?
        GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );

        if( poBestOverview != this )
        {
            return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
                                                 panHistogram,
                                                 bIncludeOutOfRange, bApproxOK,
                                                 pfnProgress, pProgressData );
        }
    }

/* -------------------------------------------------------------------- */
/*      Try with source bands.                                          */
/* -------------------------------------------------------------------- */
    if ( nRecursionCounter > 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "VRTSourcedRasterBand::GetHistogram() called recursively on the same band. "
                  "It looks like the VRT is referencing itself." );
        return CE_Failure;
    }
    nRecursionCounter ++;

    CPLErr eErr = papoSources[0]->GetHistogram(GetXSize(), GetYSize(), dfMin, dfMax, nBuckets,
                                               panHistogram,
                                               bIncludeOutOfRange, bApproxOK,
                                               pfnProgress, pProgressData);
    if (eErr != CE_None)
    {
        eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
                                                  nBuckets, panHistogram,
                                                  bIncludeOutOfRange, bApproxOK,
                                                  pfnProgress, pProgressData );
        nRecursionCounter --;
        return eErr;
    }

    nRecursionCounter --;

    return CE_None;
}

/************************************************************************/
/*                             AddSource()                              */
/************************************************************************/

CPLErr VRTSourcedRasterBand::AddSource( VRTSource *poNewSource )

{
    nSources++;

    papoSources = (VRTSource **)
        CPLRealloc(papoSources, sizeof(void*) * nSources);
    papoSources[nSources-1] = poNewSource;

    ((VRTDataset *)poDS)->SetNeedsFlush();

    return CE_None;
}

/************************************************************************/
/*                              VRTAddSource()                          */
/************************************************************************/

/**
 * @see VRTSourcedRasterBand::AddSource().
 */

CPLErr CPL_STDCALL VRTAddSource( VRTSourcedRasterBandH hVRTBand,
                                 VRTSourceH hNewSource )
{
    VALIDATE_POINTER1( hVRTBand, "VRTAddSource", CE_Failure );

    return ((VRTSourcedRasterBand *) hVRTBand)->
        AddSource( (VRTSource *)hNewSource );
}

/************************************************************************/
/*                              XMLInit()                               */
/************************************************************************/

CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
                                      const char *pszVRTPath )

{
    CPLErr eErr;

    eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
    if( eErr != CE_None )
        return eErr;

/* -------------------------------------------------------------------- */
/*      Validate a bit.                                                 */
/* -------------------------------------------------------------------- */
    if( psTree == NULL || psTree->eType != CXT_Element
        || (!EQUAL(psTree->pszValue,"VRTSourcedRasterBand")
            && !EQUAL(psTree->pszValue,"VRTRasterBand")
	    && !EQUAL(psTree->pszValue,"VRTDerivedRasterBand")) )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Invalid node passed to VRTSourcedRasterBand::XMLInit()." );
        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Process sources.                                                */
/* -------------------------------------------------------------------- */
    CPLXMLNode  *psChild;
    VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );

    for( psChild = psTree->psChild;
         psChild != NULL && poDriver != NULL;
         psChild = psChild->psNext)
    {
        VRTSource *poSource;

        if( psChild->eType != CXT_Element )
            continue;

        CPLErrorReset();
        poSource = poDriver->ParseSource( psChild, pszVRTPath );
        if( poSource != NULL )
            AddSource( poSource );
        else if( CPLGetLastErrorType() != CE_None )
            return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Done.                                                           */
/* -------------------------------------------------------------------- */
    if( nSources == 0 )
        CPLDebug( "VRT", "No valid sources found for band in VRT file:\n%s",
                  pszVRTPath ? pszVRTPath : "(null)" );

    return CE_None;
}

/************************************************************************/
/*                           SerializeToXML()                           */
/************************************************************************/

CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )

{
    CPLXMLNode *psTree;

    psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
    CPLXMLNode* psLastChild = psTree->psChild;
    while( psLastChild != NULL && psLastChild->psNext != NULL )
        psLastChild = psLastChild->psNext;

/* -------------------------------------------------------------------- */
/*      Process Sources.                                                */
/* -------------------------------------------------------------------- */
    for( int iSource = 0; iSource < nSources; iSource++ )
    {
        CPLXMLNode      *psXMLSrc;

        psXMLSrc = papoSources[iSource]->SerializeToXML( pszVRTPath );

        if( psXMLSrc != NULL )
        {
            if( psLastChild == NULL )
                psTree->psChild = psXMLSrc;
            else
                psLastChild->psNext = psXMLSrc;
            psLastChild = psXMLSrc;
        }
    }

    return psTree;
}

/************************************************************************/
/*                          ConfigureSource()                           */
/************************************************************************/

void VRTSourcedRasterBand::ConfigureSource(VRTSimpleSource *poSimpleSource,
                                           GDALRasterBand *poSrcBand,
                                           int bAddAsMaskBand,
                                           int nSrcXOff, int nSrcYOff,
                                           int nSrcXSize, int nSrcYSize,
                                           int nDstXOff, int nDstYOff,
                                           int nDstXSize, int nDstYSize)
{
/* -------------------------------------------------------------------- */
/*      Default source and dest rectangles.                             */
/* -------------------------------------------------------------------- */
    if( nSrcYSize == -1 )
    {
        nSrcXOff = 0;
        nSrcYOff = 0;
        nSrcXSize = poSrcBand->GetXSize();
        nSrcYSize = poSrcBand->GetYSize();
    }

    if( nDstYSize == -1 )
    {
        nDstXOff = 0;
        nDstYOff = 0;
        nDstXSize = nRasterXSize;
        nDstYSize = nRasterYSize;
    }

    if( bAddAsMaskBand )
        poSimpleSource->SetSrcMaskBand( poSrcBand );
    else
        poSimpleSource->SetSrcBand( poSrcBand );
    poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
    poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );

/* -------------------------------------------------------------------- */
/*      Default source and dest rectangles.                             */
/* -------------------------------------------------------------------- */
    if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
         nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
        bEqualAreas = TRUE;

/* -------------------------------------------------------------------- */
/*      If we can get the associated GDALDataset, add a reference to it.*/
/* -------------------------------------------------------------------- */
    if( poSrcBand->GetDataset() != NULL )
        poSrcBand->GetDataset()->Reference();

}

/************************************************************************/
/*                          AddSimpleSource()                           */
/************************************************************************/

CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
                                       int nSrcXOff, int nSrcYOff,
                                       int nSrcXSize, int nSrcYSize,
                                       int nDstXOff, int nDstYOff,
                                       int nDstXSize, int nDstYSize,
                                       const char *pszResampling,
                                       double dfNoDataValue )

{
/* -------------------------------------------------------------------- */
/*      Create source.                                                  */
/* -------------------------------------------------------------------- */
    VRTSimpleSource *poSimpleSource;

    if( pszResampling != NULL && EQUALN(pszResampling,"aver",4) )
        poSimpleSource = new VRTAveragedSource();
    else
    {
        poSimpleSource = new VRTSimpleSource();
        if( dfNoDataValue != VRT_NODATA_UNSET )
            CPLError(
                CE_Warning, CPLE_AppDefined,
                "NODATA setting not currently supported for nearest\n"
                "neighbour sampled simple sources on Virtual Datasources." );
    }

    ConfigureSource(poSimpleSource,
                    poSrcBand,
                    FALSE,
                    nSrcXOff, nSrcYOff,
                    nSrcXSize, nSrcYSize,
                    nDstXOff, nDstYOff,
                    nDstXSize, nDstYSize);

    if( dfNoDataValue != VRT_NODATA_UNSET )
        poSimpleSource->SetNoDataValue( dfNoDataValue );

/* -------------------------------------------------------------------- */
/*      add to list.                                                    */
/* -------------------------------------------------------------------- */
    return AddSource( poSimpleSource );
}

/************************************************************************/
/*                         AddMaskBandSource()                          */
/************************************************************************/

/* poSrcBand is not the mask band, but the band from which the mask band is taken */
CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
                                                int nSrcXOff, int nSrcYOff,
                                                int nSrcXSize, int nSrcYSize,
                                                int nDstXOff, int nDstYOff,
                                                int nDstXSize, int nDstYSize )
{
/* -------------------------------------------------------------------- */
/*      Create source.                                                  */
/* -------------------------------------------------------------------- */
    VRTSimpleSource* poSimpleSource = new VRTSimpleSource();

    ConfigureSource(poSimpleSource,
                    poSrcBand,
                    TRUE,
                    nSrcXOff, nSrcYOff,
                    nSrcXSize, nSrcYSize,
                    nDstXOff, nDstYOff,
                    nDstXSize, nDstYSize);

/* -------------------------------------------------------------------- */
/*      add to list.                                                    */
/* -------------------------------------------------------------------- */
    return AddSource( poSimpleSource );
}

/************************************************************************/
/*                         VRTAddSimpleSource()                         */
/************************************************************************/

/**
 * @see VRTSourcedRasterBand::AddSimpleSource().
 */

CPLErr CPL_STDCALL VRTAddSimpleSource( VRTSourcedRasterBandH hVRTBand,
                                       GDALRasterBandH hSrcBand,
                                       int nSrcXOff, int nSrcYOff,
                                       int nSrcXSize, int nSrcYSize,
                                       int nDstXOff, int nDstYOff,
                                       int nDstXSize, int nDstYSize,
                                       const char *pszResampling,
                                       double dfNoDataValue )
{
    VALIDATE_POINTER1( hVRTBand, "VRTAddSimpleSource", CE_Failure );

    return ((VRTSourcedRasterBand *) hVRTBand)->AddSimpleSource(
                                            (GDALRasterBand *)hSrcBand,
                                            nSrcXOff, nSrcYOff,
                                            nSrcXSize, nSrcYSize,
                                            nDstXOff, nDstYOff,
                                            nDstXSize, nDstYSize,
                                            pszResampling, dfNoDataValue );
}

/************************************************************************/
/*                          AddComplexSource()                          */
/************************************************************************/

CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
                                               int nSrcXOff, int nSrcYOff,
                                               int nSrcXSize, int nSrcYSize,
                                               int nDstXOff, int nDstYOff,
                                               int nDstXSize, int nDstYSize,
                                               double dfScaleOff,
                                               double dfScaleRatio,
                                               double dfNoDataValue,
                                               int nColorTableComponent)

{
/* -------------------------------------------------------------------- */
/*      Create source.                                                  */
/* -------------------------------------------------------------------- */
    VRTComplexSource *poSource;

    poSource = new VRTComplexSource();

    ConfigureSource(poSource,
                    poSrcBand,
                    FALSE,
                    nSrcXOff, nSrcYOff,
                    nSrcXSize, nSrcYSize,
                    nDstXOff, nDstYOff,
                    nDstXSize, nDstYSize);

/* -------------------------------------------------------------------- */
/*      Set complex parameters.                                         */
/* -------------------------------------------------------------------- */
    if( dfNoDataValue != VRT_NODATA_UNSET )
        poSource->SetNoDataValue( dfNoDataValue );

    if( dfScaleOff != 0.0 || dfScaleRatio != 1.0 )
        poSource->SetLinearScaling(dfScaleOff, dfScaleRatio);

    poSource->SetColorTableComponent(nColorTableComponent);

/* -------------------------------------------------------------------- */
/*      add to list.                                                    */
/* -------------------------------------------------------------------- */
    return AddSource( poSource );
}

/************************************************************************/
/*                         VRTAddComplexSource()                        */
/************************************************************************/

/**
 * @see VRTSourcedRasterBand::AddComplexSource().
 */

CPLErr CPL_STDCALL VRTAddComplexSource( VRTSourcedRasterBandH hVRTBand,
                                        GDALRasterBandH hSrcBand,
                                        int nSrcXOff, int nSrcYOff,
                                        int nSrcXSize, int nSrcYSize,
                                        int nDstXOff, int nDstYOff,
                                        int nDstXSize, int nDstYSize,
                                        double dfScaleOff,
                                        double dfScaleRatio,
                                        double dfNoDataValue )
{
    VALIDATE_POINTER1( hVRTBand, "VRTAddComplexSource", CE_Failure );

    return ((VRTSourcedRasterBand *) hVRTBand)->AddComplexSource(
                                            (GDALRasterBand *)hSrcBand,
                                            nSrcXOff, nSrcYOff,
                                            nSrcXSize, nSrcYSize,
                                            nDstXOff, nDstYOff,
                                            nDstXSize, nDstYSize,
                                            dfScaleOff, dfScaleRatio,
                                            dfNoDataValue );
}

/************************************************************************/
/*                           AddFuncSource()                            */
/************************************************************************/

CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
                                     void *pCBData, double dfNoDataValue )

{
/* -------------------------------------------------------------------- */
/*      Create source.                                                  */
/* -------------------------------------------------------------------- */
    VRTFuncSource *poFuncSource = new VRTFuncSource;

    poFuncSource->fNoDataValue = (float) dfNoDataValue;
    poFuncSource->pfnReadFunc = pfnReadFunc;
    poFuncSource->pCBData = pCBData;
    poFuncSource->eType = GetRasterDataType();

/* -------------------------------------------------------------------- */
/*      add to list.                                                    */
/* -------------------------------------------------------------------- */
    return AddSource( poFuncSource );
}

/************************************************************************/
/*                          VRTAddFuncSource()                          */
/************************************************************************/

/**
 * @see VRTSourcedRasterBand::AddFuncSource().
 */

CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
                                     VRTImageReadFunc pfnReadFunc,
                                     void *pCBData, double dfNoDataValue )
{
    VALIDATE_POINTER1( hVRTBand, "VRTAddFuncSource", CE_Failure );

    return ((VRTSourcedRasterBand *) hVRTBand)->
        AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
}

/************************************************************************/
/*                      GetMetadataDomainList()                         */
/************************************************************************/

char **VRTSourcedRasterBand::GetMetadataDomainList()
{
    return CSLAddString(GDALRasterBand::GetMetadataDomainList(), "LocationInfo");
}

/************************************************************************/
/*                          GetMetadataItem()                           */
/************************************************************************/

const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
                                                   const char * pszDomain )

{
/* ==================================================================== */
/*      LocationInfo handling.                                          */
/* ==================================================================== */
    if( pszDomain != NULL
        && EQUAL(pszDomain,"LocationInfo")
        && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
    {
        int iPixel, iLine;

/* -------------------------------------------------------------------- */
/*      What pixel are we aiming at?                                    */
/* -------------------------------------------------------------------- */
        if( EQUALN(pszName,"Pixel_",6) )
        {
            if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
                return NULL;
        }
        else if( EQUALN(pszName,"GeoPixel_",9) )
        {
            double adfGeoTransform[6];
            double adfInvGeoTransform[6];
            double dfGeoX, dfGeoY;

            dfGeoX = CPLAtof(pszName + 9);
            const char* pszUnderscore = strchr(pszName + 9, '_');
            if( !pszUnderscore )
                return NULL;
            dfGeoY = CPLAtof(pszUnderscore + 1);

            if( GetDataset() == NULL )
                return NULL;

            if( GetDataset()->GetGeoTransform( adfGeoTransform ) != CE_None )
                return NULL;

            if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
                return NULL;

            iPixel = (int) floor(
                adfInvGeoTransform[0]
                + adfInvGeoTransform[1] * dfGeoX
                + adfInvGeoTransform[2] * dfGeoY );
            iLine = (int) floor(
                adfInvGeoTransform[3]
                + adfInvGeoTransform[4] * dfGeoX
                + adfInvGeoTransform[5] * dfGeoY );
        }
        else
            return NULL;

        if( iPixel < 0 || iLine < 0
            || iPixel >= GetXSize()
            || iLine >= GetYSize() )
            return NULL;

/* -------------------------------------------------------------------- */
/*      Find the file(s) at this location.                              */
/* -------------------------------------------------------------------- */
        char **papszFileList = NULL;
        int nListMaxSize = 0, nListSize = 0;
        CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
                                              CPLHashSetEqualStr,
                                              NULL);

        for( int iSource = 0; iSource < nSources; iSource++ )
        {
            double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
            int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
            int nOutXOff, nOutYOff, nOutXSize, nOutYSize;

            if (!papoSources[iSource]->IsSimpleSource())
                continue;

            VRTSimpleSource *poSrc = (VRTSimpleSource *) papoSources[iSource];

            if( !poSrc->GetSrcDstWindow( iPixel, iLine, 1, 1, 1, 1,
                                         &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                                         &nReqXOff, &nReqYOff,
                                         &nReqXSize, &nReqYSize,
                                         &nOutXOff, &nOutYOff,
                                         &nOutXSize, &nOutYSize ) )
                continue;

            poSrc->GetFileList( &papszFileList, &nListSize, &nListMaxSize,
                                hSetFiles );
        }

/* -------------------------------------------------------------------- */
/*      Format into XML.                                                */
/* -------------------------------------------------------------------- */
        int i;

        osLastLocationInfo = "<LocationInfo>";
        for( i = 0; i < nListSize; i++ )
        {
            osLastLocationInfo += "<File>";
            char* pszXMLEscaped = CPLEscapeString(papszFileList[i], -1, CPLES_XML);
            osLastLocationInfo += pszXMLEscaped;
            CPLFree(pszXMLEscaped);
            osLastLocationInfo += "</File>";
        }
        osLastLocationInfo += "</LocationInfo>";

        CSLDestroy( papszFileList );
        CPLHashSetDestroy( hSetFiles );

        return osLastLocationInfo.c_str();
    }

/* ==================================================================== */
/*      Other domains.                                                  */
/* ==================================================================== */
    else
        return GDALRasterBand::GetMetadataItem( pszName, pszDomain );
}

/************************************************************************/
/*                            GetMetadata()                             */
/************************************************************************/

char **VRTSourcedRasterBand::GetMetadata( const char *pszDomain )

{
/* ==================================================================== */
/*      vrt_sources domain handling.                                    */
/* ==================================================================== */
    if( pszDomain != NULL && EQUAL(pszDomain,"vrt_sources") )
    {
        CSLDestroy(papszSourceList);
        papszSourceList = NULL;

/* -------------------------------------------------------------------- */
/*      Process SimpleSources.                                          */
/* -------------------------------------------------------------------- */
        for( int iSource = 0; iSource < nSources; iSource++ )
        {
            CPLXMLNode      *psXMLSrc;
            char            *pszXML;

            psXMLSrc = papoSources[iSource]->SerializeToXML( NULL );
            if( psXMLSrc == NULL )
                continue;

            pszXML = CPLSerializeXMLTree( psXMLSrc );

            papszSourceList =
                CSLSetNameValue( papszSourceList,
                                 CPLSPrintf( "source_%d", iSource ), pszXML );
            CPLFree( pszXML );
            CPLDestroyXMLNode( psXMLSrc );
        }

        return papszSourceList;
    }

/* ==================================================================== */
/*      Other domains.                                                  */
/* ==================================================================== */
    else
        return GDALRasterBand::GetMetadata( pszDomain );
}

/************************************************************************/
/*                          SetMetadataItem()                           */
/************************************************************************/

CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName,
                                              const char *pszValue,
                                              const char *pszDomain )

{
    CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
              pszName, pszValue, pszDomain );

    if( pszDomain != NULL
        && EQUAL(pszDomain,"new_vrt_sources") )
    {
        VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );

        CPLXMLNode *psTree = CPLParseXMLString( pszValue );
        VRTSource *poSource;

        if( psTree == NULL )
            return CE_Failure;

        poSource = poDriver->ParseSource( psTree, NULL );
        CPLDestroyXMLNode( psTree );

        if( poSource != NULL )
            return AddSource( poSource );
        else
            return CE_Failure;
    }
    else if( pszDomain != NULL
        && EQUAL(pszDomain,"vrt_sources") )
    {
        int iSource;
        if (sscanf(pszName, "source_%d", &iSource) != 1 || iSource < 0 ||
            iSource >= nSources)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "%s metadata item name is not recognized. "
                     "Should be between source_0 and source_%d",
                     pszName, nSources - 1);
            return CE_Failure;
        }

        VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );

        CPLXMLNode *psTree = CPLParseXMLString( pszValue );
        VRTSource *poSource;

        if( psTree == NULL )
            return CE_Failure;

        poSource = poDriver->ParseSource( psTree, NULL );
        CPLDestroyXMLNode( psTree );

        if( poSource != NULL )
        {
            delete papoSources[iSource];
            papoSources[iSource] = poSource;
            ((VRTDataset *)poDS)->SetNeedsFlush();
            return CE_None;
        }
        else
            return CE_Failure;
    }
    else
        return VRTRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
}

/************************************************************************/
/*                            SetMetadata()                             */
/************************************************************************/

CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDomain )

{
    if( pszDomain != NULL
        && (EQUAL(pszDomain,"new_vrt_sources")
            || EQUAL(pszDomain,"vrt_sources")) )
    {
        VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
        CPLErr eErr;
        int    i;

        if( EQUAL(pszDomain,"vrt_sources") )
        {
            for( int i = 0; i < nSources; i++ )
                delete papoSources[i];
            CPLFree( papoSources );
            papoSources = NULL;
            nSources = 0;
        }

        for( i = 0; i < CSLCount(papszNewMD); i++ )
        {
            const char *pszXML = CPLParseNameValue( papszNewMD[i], NULL );
            CPLXMLNode *psTree = CPLParseXMLString( pszXML );
            VRTSource *poSource;

            if( psTree == NULL )
                return CE_Failure;

            poSource = poDriver->ParseSource( psTree, NULL );
            CPLDestroyXMLNode( psTree );

            if( poSource != NULL )
            {
                eErr = AddSource( poSource );
                if( eErr != CE_None )
                    return eErr;
            }
            else
                return CE_Failure;
        }

        return CE_None;
    }
    else
        return VRTRasterBand::SetMetadata( papszNewMD, pszDomain );
}

/************************************************************************/
/*                             GetFileList()                            */
/************************************************************************/

void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
                                       int *pnMaxSize, CPLHashSet* hSetFiles)
{
    for( int i = 0; i < nSources; i++ )
    {
        papoSources[i]->GetFileList(ppapszFileList, pnSize,
                                    pnMaxSize, hSetFiles);
    }

    VRTRasterBand::GetFileList( ppapszFileList, pnSize,
                                pnMaxSize, hSetFiles);
}

/************************************************************************/
/*                        CloseDependentDatasets()                      */
/************************************************************************/

int VRTSourcedRasterBand::CloseDependentDatasets()
{
    if (nSources == 0)
        return FALSE;

    for( int i = 0; i < nSources; i++ )
        delete papoSources[i];

    CPLFree( papoSources );
    papoSources = NULL;
    nSources = 0;

    return TRUE;
}


text:
<input class="input-query" placeholder="Please, enter the skill name or knowledge level..." ng-model="searchParam">

{{skill.name}}

Knowledge level

{{skill.knowledgeLevel}}

Knowledge level

{{skill.knowledgeLevel}}

Knowledge

{{skill.knowledgeLevel}}


text:
function serializeTable(val, name, skipnewlines, depth)
    skipnewlines = skipnewlines or false
    depth = depth or 0

    local tmp = string.rep(" ", depth)

    if name then tmp = tmp .. name .. " = " end

    if type(val) == "table" then
        tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")

        for k, v in pairs(val) do
            tmp =  tmp .. serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "")
        end

        tmp = tmp .. string.rep(" ", depth) .. "}"
    elseif type(val) == "number" then
        tmp = tmp .. tostring(val)
    elseif type(val) == "string" then
        tmp = tmp .. string.format("%q", val)
    elseif type(val) == "boolean" then
        tmp = tmp .. (val and "true" or "false")
    else
        tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
    end

    return tmp
end

function dt_dumpItemStack(value)
    local tmp=""
    tmp =tmp.." name ["..value.name .."]"
    tmp =tmp.." type ["..value.type .."]"
	  tmp =tmp.." count ["..tostring(value.count) .."]"
end

function dt_dumpEntity(value,name,skipnewlines)
    local tmp=""
    skipnewlines=true
    if name and type(name) == "string" then tmp = tmp .. name .. " = " end
    tmp =tmp.." name ["..value.name .."]"  .. (not skipnewlines and "\n" or "")
    tmp =tmp.." type ["..value.type .."]"  .. (not skipnewlines and "\n" or "")
    tmp =tmp.." surface ["..value.surface.name..":"..tostring(value.surface.index) .."]"  .. (not skipnewlines and "\n" or "")
    tmp =tmp.." position [ x="..tostring(value.position.x).." y="..tostring(value.position.y) .."]"  .. (not skipnewlines and "\n" or "")
    if value.type == "transport-belt" then
--      for k,v in pairs(value) do
--        tmp =tmp.."{"..k.."}="..tostring(v).." "
--      end

      local line=value.get_transport_line(1)
      local cnt=line.get_item_count()
      local cmap=line.get_contents()
      for k,v in pairs(cmap) do
        tmp =tmp.."{"..k.."}="..tostring(v).." "
      end

--      local lm=getmetatable(line)
--      if lm  ~= nil then
--        tmp =tmp.."mata= "
--        for k,v in pairs(lm) do
--          tmp =tmp.."{"..k.."}="..tostring(v).." "
--        end
--      end

      if cnt >0 then
        tmp =  tmp .. "[line 1 " .. tostring(cnt).."]"
      end

      line=value.get_transport_line(2)
      cnt=line.get_item_count()
      if cnt >0 then
        tmp =  tmp .. "[line 2 " .. tostring(cnt).."]"
      end

    end

    return tmp
end

function dt_dumpItemTable(val, name, skipnewlines, depth)
    skipnewlines = skipnewlines or false
    depth = depth or 0

    local tmp = string.rep(" ", depth)

    if name then tmp = tmp .. name .. " = " end

    if type(val) == "table" then
      for  name,value in pairs(val) do
        tmp =  tmp .. dt_dumpEntity(value,name,true) .. (not skipnewlines and "\n" or "")
      end
    end

    return tmp
end

function string:split( inSplitPattern, outResults )

   if not outResults then
      outResults = { }
   end
   local theStart = 1
   local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
   while theSplitStart do
      table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
      theStart = theSplitEnd + 1
      theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
   end
   table.insert( outResults, string.sub( self, theStart ) )
   return outResults
end

function debugLog(message)
  if true then -- set for debug
    game.player.print(message)
  end
end

function table.val_to_str ( v )
  if "string" == type( v ) then
    v = string.gsub( v, "\n", "\\n" )
    if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
      return "'" .. v .. "'"
    end
    return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
  else
    return "table" == type( v ) and table.tostring( v ) or
      tostring( v )
  end
end

function table.key_to_str ( k )
  if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
    return k
  else
    return "[" .. table.val_to_str( k ) .. "]"
  end
end

function table.tostring( tbl )
  local result, done = {}, {}
  for k, v in ipairs( tbl ) do
    table.insert( result, table.val_to_str( v ) )
    done[ k ] = true
  end
  for k, v in pairs( tbl ) do
    if not done[ k ] then
      table.insert( result,
        table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
    end
  end
  return "{" .. table.concat( result, "," ) .. "}"
end


text:
layout: blip
name: "Responsive Design"
status: "Adopted"
first_added: "July 2016"
---


text:
*****************
ISD CA Operations
*****************

.. highlight:: bash

Once a new ISD is established through the completion of a key signing ceremony,
certificates can be generated for the Certificate Authorities and ASes of
the ISD.

Trust within an ISD flows from the TRC. The TRC contains one or more Root Certificates,
which are used to sign new CA Certificates, which are in turn used to sign one or more AS
Certificates.

The process of creating new CA Certificates is described in section `CA Certificates`_.
The process of creating new AS Certificates is described in section `AS Certificates`_.

To follow the steps in this document, ``openssl`` version ``1.1.1d`` or later is
required.

CA Certificates
===============

CA Certificates in SCION are always signed by a Root Certificate, which is
contained in the TRC. Because the Root Certificate is usually owned by the same
entity that also acts as a CA, the entity is able to perform the signing step by
itself.

Creating the initial CA Certificate
-----------------------------------

The steps in creating a new CA Certificate are:

#. Define the configuration of the CA Certificate in accordance with
   :ref:`the SCION requirements <cp-ca-certificate>`.
#. Create a new key pair.
#. Create a Certificate Signing Request using the key pair.
#. Use the Root Key and the Certificate Signing Request to create the new CA Certificate.

The configuration is defined in a file. OpenSSL reads the file and creates a
certificate that is compatible with SCION. An example configuration file is
included below. Note that the file includes the text ``{{.ShortOrg}}``; this
text **must** be replaced with the shortname of your organization. For example,
if your organization name is **ExampleCorp**, the line should contain ``name =
ExampleCorp Secure CA Certificate``.

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE ca_conf START
   :end-before: LITERALINCLUDE ca_conf END

.. attention::

   SCION CA certificates have short lifetimes (a lifetime of 7 days is recommended).

Once the file is ready, the rest of the steps can be executed through a series
of ``openssl`` commands.

These commands contain must be configured using the following values:

- CA Certificate validity start date. Prior to this date, the certificate is
  not considered valid. To configure this, replace occurrences of ``$STARTDATE``
  with the date in ``YYYYMMDDHHMMSSZ`` notation. For example, June 24th, 2020 UTC
  at noon is formatted as ``20200624120000Z``.
- CA Certificate validity end date. After this date, the certificate is no
  longer valid. To configure this, replace occurrences of ``$ENDDATE`` with
  the desired date. This uses the same notation as the ``$STARTDATE``.
- Folder where the keys are contained. To configure this, replace ``$KEYDIR`` with the folder name.

.. note::

   Note that the commands below assume that the CA Key and Root Key are found in the
   ``$KEYDIR`` folder, and have the names ``cp-ca.key`` and ``cp-root.key``. If this
   is not the case, the commands should be adjusted with the proper key locations.

Finally, to create the CA certificate, run the commands below.

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE gen_ca START
   :end-before: LITERALINCLUDE gen_ca END
   :dedent: 4

After generating the certificate, check that the output is reasonable:

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE check_ca START
   :end-before: LITERALINCLUDE check_ca END
   :dedent: 4

The signature algorithm must be ``ecdsa-with-SHA512``.

The certificate can be validated with with the ``scion-pki`` binary:

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE check_ca_type START
   :end-before: LITERALINCLUDE check_ca_type END
   :dedent: 4

Creating future CA Certificates
-------------------------------

Because CA certificates are created by signing them with the Root certificate,
the process for creating future CA certificates is the same as the initial one.

To comply with custom security policies that dictate that a Root Key should sit
behind an air gap, multiple CA certificates can be pre-generated for the same
entity. Such CA certificates should be generated with overlapping validity
periods to allow for smooth transition from one to the next.

AS Certificates
===============

AS Certificates in SCION are always signed by a CA Certificate, which is in turn
signed by the Root Certificate contained in the TRC.

Because the entities applying for an AS certificate (the ASes) are sometimes different from
the CA entity signing the certificate (the CA), we separate the steps in this section
into two: the AS steps and the CA steps.

.. important::

   SCION Certificate Authorities are also SCION ASes. This means that every CA must also
   create an AS certificate for itself. In this specific case, the two entities in this
   section (the AS and the CA) are the same.

Creating the initial AS Certificate
-----------------------------------

The steps in creating a new AS Certificate are:

#. The AS defines the configuration of the AS Certificate in accordance with
   :ref:`the SCION requirements <cp-as-certificate>`.
#. The AS creates a new key pair.
#. The AS creates a Certificate Signing Request using the key pair.
#. (If the AS and CA are different entities) The AS sends the Certificate Signing Request to the CA.
#. The CA uses its CA Key and the Certificate Signing Request to create the new AS Certificate.
#. (If the AS and CA are different entities) The CA sends the AS Certificate back to the AS.

The configuration is defined in a file. OpenSSL reads the file and creates a
certificate that is compatible with SCION. An example configuration file is
included below. Note that the file includes the text ``{{.ShortOrg}}``; this
text **must** be replaced with the shortname of your organization. For example,
if your organization name is **ExampleCorp**, the line should contain ``name =
ExampleCorp Secure CA Certificate``.

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE as_conf START
   :end-before: LITERALINCLUDE as_conf END

.. attention::

   SCION AS certificates have short lifetimes (a lifetime of 3 days is recommended).

To create the key pair and certificate signing request (CSR), the AS then runs
the OpenSSL commands below. In these commands, replace ``$KEYDIR`` with the
folder where private keys should be stored:

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE gen_as_as_steps START
   :end-before: LITERALINCLUDE gen_as_as_steps END
   :dedent: 4

If the AS and CA are different entities, the certificate signing request can
then be sent to a CA for signing.

This step is performed by an entity that is a CA in the ISD. The CA creates
the certificate using its private key and the certificate signing request
received from the AS. The CA must also define the following:

- CA Certificate validity start date. Prior to this date, the certificate is
  not considered valid. To configure this, in the command below replace
  occurrences of ``$STARTDATE`` with the date in ``YYYYMMDDHHMMSSZ`` notation.
  For example, June 24th, 2020 UTC at noon is formatted as ``20200624120000Z``.
- CA Certificate validity end date. After this date, the certificate is no
  longer valid. To configure this, in the command below replace occurrences of
  ``$ENDDATE`` with the desired date. This uses the same notation as the
  ``$STARTDATE``.

Additionally, the CA should set ``$KEYDIR`` to the folder in which the private
key file (the file is called ``cp-ca.key``, in this example) is stored.

To create the certificate, the CA runs:

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE gen_as_ca_steps START
   :end-before: LITERALINCLUDE gen_as_ca_steps END
   :dedent: 4

After generating the certificate, check that the output is reasonable:

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE check_as START
   :end-before: LITERALINCLUDE check_as END
   :dedent: 4

The signature algorithm must be ``ecdsa-with-SHA512``.

The certificate can be validated with with the ``scion-pki`` binary:

.. literalinclude:: crypto_lib.sh
   :start-after: LITERALINCLUDE check_as_type START
   :end-before: LITERALINCLUDE check_as_type END
   :dedent: 4

If the AS and CA are different entities, the CA should then send the certificate
back to the AS that request it.

Creating future AS certificates
-------------------------------

Because AS certificates are created by signing them with the CA certificate,
the process for creating future CA certificates is the same as the initial one.

In a running ISD, AS certificates are usually built automatically by the
SCION control plane.


text:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Poseidon.Recovery.ClientDx
{
    using Poseidon.Base.Framework;
    using Poseidon.Base.System;
    using Poseidon.Winform.Base;
    using Poseidon.Recovery.Core.BL;
    using Poseidon.Recovery.Core.DL;

    /// <summary>
    /// 表具设置窗体
    /// </summary>
    public partial class FrmMeterSet : BaseSingleForm
    {
        #region Field
        /// <summary>
        /// 当前关联账户
        /// </summary>
        private Account currentAccount;
        #endregion //Field

        #region Constructor
        public FrmMeterSet(string accountId)
        {
            InitializeComponent();

            InitData(accountId);
        }
        #endregion //Constructor

        #region Function
        private void InitData(string id)
        {
            this.currentAccount = BusinessFactory<AccountBusiness>.Instance.FindById(id);
        }

        protected override void InitForm()
        {
            this.txtAccountName.Text = this.currentAccount.Name;
            this.meterGrid.DataSource = this.currentAccount.Meters;

            this.meterGrid.Init();
            base.InitForm();
        }

        /// <summary>
        /// 输入检查
        /// </summary>
        /// <returns></returns>
        private Tuple<bool, string> CheckInput()
        {
            string errorMessage = "";

            foreach (var item in this.meterGrid.DataSource)
            {
                if (string.IsNullOrEmpty(item.Name))
                {
                    errorMessage = "名称不能为空";
                    return new Tuple<bool, string>(false, errorMessage);
                }
                if (string.IsNullOrEmpty(item.Number))
                {
                    errorMessage = "表号不能为空";
                    return new Tuple<bool, string>(false, errorMessage);
                }
            }

            return new Tuple<bool, string>(true, "");
        }

        /// <summary>
        /// 设置对象
        /// </summary>
        /// <param name="entity"></param>
        private void SetEntity(List<Meter> entity)
        {
            foreach (var item in entity)
            {
                item.Address = item.Address ?? "";
                item.Remark = item.Remark ?? "";
            }
        }
        #endregion //Function

        #region Event
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConfirm_Click(object sender, EventArgs e)
        {
            this.meterGrid.CloseEditor();

            var input = CheckInput();
            if (!input.Item1)
            {
                MessageUtil.ShowError(input.Item2);
                return;
            }

            try
            {
                var data = this.meterGrid.DataSource;
                SetEntity(data);

                BusinessFactory<AccountBusiness>.Instance.SetMeters(this.currentAccount.Id, data);

                MessageUtil.ShowInfo("保存成功");
                this.Close();
            }
            catch (PoseidonException pe)
            {
                MessageUtil.ShowError(string.Format("保存失败,错误消息:{0}", pe.Message));
            }
        }
        #endregion //Event
    }
}