text:
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { OpenViduService, ParticipantAbstractModel, RecordingInfo, TokenModel } from 'openvidu-angular';
import { Session } from 'openvidu-browser';
import { CaptionsLangOption } from '../../../projects/openvidu-angular/src/lib/models/caption.model';

/**
 *
 * **OpenviduWebComponentComponent** is a wrapper of the {@link VideoconferenceComponent} which allows to generate and export the OpenVidu Webcomponent.
 * **It is not included in the library**.
 */
@Component({
	templateUrl: './openvidu-webcomponent.component.html'
})
export class OpenviduWebComponentComponent implements OnInit {
	/**
	 * @internal
	 */
	_tokens: TokenModel;
	/**
	 * @internal
	 */
	_minimal: boolean = false;
	/**
	 * @internal
	 */

	/**
	 * @internal
	 */
	_lang: string = '';

	/**
	 * @internal
	 */
	_captionsLang: string = '';

	/**
	 * @internal
	 */
	_captionsLangOptions: CaptionsLangOption;

	/**
	 * @internal
	 */
	_participantName: string;
	/**
	 * @internal
	 */
	_prejoin: boolean = true;
	/**
	 * @internal
	 */
	_videoMuted: boolean = false;
	/**
	 * @internal
	 */
	_audioMuted: boolean = false;
	/**
	 * @internal
	 */
	_toolbarScreenshareButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarRecordingButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarFullscreenButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarBackgroundEffectsButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarSettingsButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarLeaveButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarChatPanelButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarActivitiesPanelButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarParticipantsPanelButton: boolean = true;
	/**
	 * @internal
	 */
	_toolbarDisplayLogo: boolean = true;
	/**
	 * @internal
	 */
	_toolbarDisplaySessionName: boolean = true;
	/**
	 * @internal
	 */
	_toolbarCaptionsButton: boolean = true;
	/**
	 * @internal
	 */
	_streamDisplayParticipantName: boolean = true;
	/**
	 * @internal
	 */
	_streamDisplayAudioDetection: boolean = true;
	/**
	 * @internal
	 */
	_streamSettingsButton: boolean = true;
	/**
	 * @internal
	 */
	_participantPanelItemMuteButton: boolean = true;
	/**
	 * @internal
	 */
	_recordingActivityRecordingError: any = null;
	/**
	 * @internal
	 */
	_activitiesPanelRecordingActivity: boolean = true;

	/**
	 * @internal
	 */
	_recordingActivityRecordingsList: RecordingInfo[] = [];

	/**
	 * The **minimal** attribute applies a minimal UI hiding all controls except for cam and mic.
	 *
	 * Default: `false`
	 *
	 * @example
	 * <openvidu-webcomponent minimal="true"></openvidu-webcomponent>
	 */
	@Input() set minimal(value: string | boolean) {
		this._minimal = this.castToBoolean(value);
	}
	/**
	 * The **lang** attribute sets the default UI language.
	 *
	 * Default: `en`
	 *
	 * @example
	 * <openvidu-webcomponent lang="es"></openvidu-webcomponent>
	 */
	@Input() set lang(value: string) {
		this._lang = value;
	}
	/**
	 * The **captionsLang** attribute sets the deafult language that OpenVidu will try to recognise.
	 *
	 * It must be a valid [BCP-47](https://tools.ietf.org/html/bcp47) language tag like "en-US" or "es-ES".
	 *
	 * Default: `en-US`
	 *
	 * @example
	 * <openvidu-webcomponent captions-lang="es-ES"></openvidu-webcomponent>
	 */
	@Input() set captionsLang(value: string) {
		this._captionsLang = value;
	}
	/**
	 * The captionsLangOptions attribute sets the language options for the captions.
	 * It will override the languages provided by default.
	 * This propety is an array of objects which must comply with the {@link CaptionsLangOption} interface.
	 *
	 * Default: ```
	 * [
	 * 	{ name: 'English', ISO: 'en-US' },
	 * 	{ name: 'Español', ISO: 'es-ES' },
	 * 	{ name: 'Deutsch', ISO: 'de-DE' },
	 * 	{ name: 'Français', ISO: 'fr-FR' },
	 * 	{ name: '中国', ISO: 'zh-CN' },
	 * 	{ name: 'हिन्दी', ISO: 'hi-IN' },
	 * 	{ name: 'Italiano', ISO: 'it-IT' },
	 * 	{ name: 'やまと', ISO: 'jp-JP' },
	 * 	{ name: 'Português', ISO: 'pt-PT' }
	 * ]```
	 *
	 * @example
	 * <openvidu-webcomponent captions-lang-options="[{name:'Spanish', ISO: 'es-ES'}]"></openvidu-webcomponent>
	 */
	@Input() set captionsLangOptions(value: string | CaptionsLangOption []) {
		this._captionsLangOptions = this.castToArray(value);
	}
	/**
	 * The **participantName** attribute sets the participant name. It can be useful for aplications which doesn't need the prejoin page.
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent participant-name="MY_NAME"></openvidu-webcomponent>
	 */
	@Input() set participantName(value: string) {
		this._participantName = value;
	}
	/**
	 * The **prejoin** attribute allows show/hide the prejoin page for selecting media devices.
	 *
	 * Default: `true`
	 *
	 * @example
	 * <openvidu-webcomponent prejoin="false"></openvidu-webcomponent>
	 */
	@Input() set prejoin(value: string | boolean) {
		this._prejoin = this.castToBoolean(value);
	}
	/**
	 * The **videoMuted** attribute allows to join the session with camera muted/unmuted.
	 *
	 * Default: `false`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent video-muted="false"></openvidu-webcomponent>
	 */
	@Input() set videoMuted(value: string | boolean) {
		this._videoMuted = this.castToBoolean(value);
	}
	/**
	 * The **audioMuted** attribute allows to join the session with microphone muted/unmuted.
	 *
	 * Default: `false`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent audio-muted="false"></openvidu-webcomponent>
	 */
	@Input() set audioMuted(value: string | boolean) {
		this._audioMuted = this.castToBoolean(value);
	}

	/**
	 * The **toolbarScreenshareButton** attribute allows show/hide the screenshare toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-screenshare-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarScreenshareButton(value: string | boolean) {
		this._toolbarScreenshareButton = this.castToBoolean(value);
	}

	/**
	 * The **toolbarRecordingButton** attribute allows show/hide the start/stop recording toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-recording-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarRecordingButton(value: string | boolean) {
		this._toolbarRecordingButton = this.castToBoolean(value);
	}
	/**
	 * The **toolbarFullscreenButton** attribute allows show/hide the fullscreen toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-fullscreen-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarFullscreenButton(value: string | boolean) {
		this._toolbarFullscreenButton = this.castToBoolean(value);
	}

	/**
	 * The **toolbarBackgroundEffectsButton** attribute allows show/hide the background effects toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-background-effects-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarBackgroundEffectsButton(value: string | boolean) {
		this._toolbarBackgroundEffectsButton = this.castToBoolean(value);
	}

	/**
	 * The **toolbarSettingsButton** attribute allows show/hide the settings toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-settings-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarSettingsButton(value: string | boolean) {
		this._toolbarSettingsButton = this.castToBoolean(value);
	}
	/**
	 * The **toolbarLeaveButton** attribute allows show/hide the leave toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-leave-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarLeaveButton(value: string | boolean) {
		this._toolbarLeaveButton = this.castToBoolean(value);
	}
	/**
	 * The **toolbarChatPanelButton** attribute allows show/hide the chat panel toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-chat-panel-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarChatPanelButton(value: string | boolean) {
		this._toolbarChatPanelButton = this.castToBoolean(value);
	}

	/**
	 * The **toolbarActivitiesPanelButton** attribute allows show/hide the activities panel toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-activities-panel-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarActivitiesPanelButton(value: string | boolean) {
		this._toolbarActivitiesPanelButton = this.castToBoolean(value);
	}
	/**
	 * The **toolbarParticipantsPanelButton** attribute allows show/hide the participants panel toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-participants-panel-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarParticipantsPanelButton(value: string | boolean) {
		this._toolbarParticipantsPanelButton = this.castToBoolean(value);
	}
	/**
	 * The **toolbarDisplayLogo** attribute allows show/hide the branding logo.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-display-logo="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarDisplayLogo(value: string | boolean) {
		this._toolbarDisplayLogo = this.castToBoolean(value);
	}
	/**
	 * The **toolbarDisplaySessionName** attribute allows show/hide the session name.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-display-session-name="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarDisplaySessionName(value: string | boolean) {
		this._toolbarDisplaySessionName = this.castToBoolean(value);
	}
	/**
	 * The **toolbarCaptionsButton** attribute allows show/hide the captions toolbar button.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent toolbar-captions-button="false"></openvidu-webcomponent>
	 */
	@Input() set toolbarCaptionsButton(value: string | boolean) {
		this._toolbarCaptionsButton = this.castToBoolean(value);
	}
	/**
	 * The **streamDisplayParticipantName** attribute allows show/hide the participants name in stream component.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent stream-display-participant-name="false"></openvidu-webcomponent>
	 */
	@Input() set streamDisplayParticipantName(value: string | boolean) {
		this._streamDisplayParticipantName = this.castToBoolean(value);
	}
	/**
	 * The **streamDisplayAudioDetection** attribute allows show/hide the participants audio detection in stream component.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent stream-display-audio-detection="false"></openvidu-webcomponent>
	 */
	@Input() set streamDisplayAudioDetection(value: string | boolean) {
		this._streamDisplayAudioDetection = this.castToBoolean(value);
	}
	/**
	 * The **streamSettingsButton** attribute allows show/hide the participants settings button in stream component.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent stream-settings-button="false"></openvidu-webcomponent>
	 */
	@Input() set streamSettingsButton(value: string | boolean) {
		this._streamSettingsButton = this.castToBoolean(value);
	}
	/**
	 * The **participantPanelItemMuteButton** attribute allows show/hide the muted button in participant panel item component.
	 *
	 * Default: `true`
	 *
	 *

	 * 	WARNING: If you want to use this parameter to OpenVidu Web Component statically, you have to replace the camelCase with a hyphen between words.

	 *
	 * @example
	 * <openvidu-webcomponent participant-panel-item-mute-button="false"></openvidu-webcomponent>
	 */
	@Input() set participantPanelItemMuteButton(value: string | boolean) {
		this._participantPanelItemMuteButton = this.castToBoolean(value);
	}

	/**
	 * The **recordingActivityRecordingError** attribute allows to show any possible error with the recording in the {@link RecordingActivityComponent}.
	 *
	 * Default: `true`
	 *
	 * @example
	 * <openvidu-webcomponent recording-activity-recording-error="false"></openvidu-webcomponent>
	 */
	@Input() set recordingActivityRecordingError(value: any) {
		this._recordingActivityRecordingError = value;
	}

	/**
	 * The **activitiesPanelRecordingActivity** attribute allows show/hide the recording activity in {@link ActivitiesPanelComponent}.
	 *
	 * Default: `true`
	 *
	 * @example
	 * <openvidu-webcomponent activity-panel-recording-activity="false"></openvidu-webcomponent>
	 */
	@Input() set activitiesPanelRecordingActivity(value: string | boolean) {
		this._activitiesPanelRecordingActivity = this.castToBoolean(value);
	}

	/**
	 * The **recordingActivityRecordingList** attribute allows show to show the recordings available for the session in {@link RecordingActivityComponent}.
	 *
	 * Default: `[]`
	 *
	 * @example
	 * <openvidu-webcomponent recording-activity-recordings-list="recordingsList"></openvidu-webcomponent>
	 */
	@Input() set recordingActivityRecordingsList(value: RecordingInfo[]) {
		this._recordingActivityRecordingsList = value;
	}

	/**
	 * Provides event notifications that fire when join button (in prejoin page) has been clicked.
	 */
	@Output() onJoinButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when leave button has been clicked.
	 */
	@Output() onToolbarLeaveButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when camera toolbar button has been clicked.
	 */
	@Output() onToolbarCameraButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when microphone toolbar button has been clicked.
	 */
	@Output() onToolbarMicrophoneButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when screenshare toolbar button has been clicked.
	 */
	@Output() onToolbarScreenshareButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when fullscreen toolbar button has been clicked.
	 */
	@Output() onToolbarFullscreenButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when participants panel button has been clicked.
	 */
	@Output() onToolbarParticipantsPanelButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when chat panel button has been clicked.
	 */
	@Output() onToolbarChatPanelButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when activities panel button has been clicked.
	 */
	@Output() onToolbarActivitiesPanelButtonClicked: EventEmitter<void> = new EventEmitter<void>();

	@Output() onToolbarStartRecordingClicked: EventEmitter<void> = new EventEmitter<void>();
	/**
	 * Provides event notifications that fire when stop recording button is clicked from {@link ToolbarComponent}.
	 *  The recording should be stopped using the REST API.
	 */
	@Output() onToolbarStopRecordingClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when start recording button is clicked {@link ActivitiesPanelComponent}.
	 *  The recording should be stopped using the REST API.
	 */
	@Output() onActivitiesPanelStartRecordingClicked: EventEmitter<void> = new EventEmitter<void>();
	/**
	 * Provides event notifications that fire when stop recording button is clicked from {@link ActivitiesPanelComponent}.
	 *  The recording should be stopped using the REST API.
	 */
	@Output() onActivitiesPanelStopRecordingClicked: EventEmitter<void> = new EventEmitter<void>();

	/**
	 * Provides event notifications that fire when download recording button is clicked from {@link ActivitiesPanelComponent}.
	 *  The recording should be downloaded using the REST API.
	 */
	@Output() onActivitiesPanelDownloadRecordingClicked: EventEmitter<string> = new EventEmitter<string>();

	/**
	 * Provides event notifications that fire when delete recording button is clicked from {@link ActivitiesPanelComponent}.
	 *  The recording should be deleted using the REST API.
	 */
	@Output() onActivitiesPanelDeleteRecordingClicked: EventEmitter<string> = new EventEmitter<string>();

	/**
	 * Provides event notifications that fire when OpenVidu Session is created.
	 * See {@link https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/Session.html openvidu-browser Session}.
	 */
	@Output() onSessionCreated: EventEmitter<Session> = new EventEmitter<Session>();

	/**
	 * Provides event notifications that fire when local participant is created.
	 */
	@Output() onParticipantCreated: EventEmitter<ParticipantAbstractModel> = new EventEmitter<ParticipantAbstractModel>();

	/**
	 * @internal
	 */
	success: boolean = false;

	/**
	 * @internal
	 */
	constructor(private host: ElementRef, private openviduService: OpenViduService) {
		this.host.nativeElement.disconnect = this.disconnect.bind(this);
	}

	ngOnInit(): void {}

	/**
	 * Tokens parameter is required to grant a participant access to a Session.
	 * This OpenVidu token will be use by each participant when connecting to a Session.
	 *
	 * This input accepts a {@link TokenModel} object type or a string type.
	 *
	 * @example
	 * <openvidu-webcomponent tokens='{"webcam":"TOKEN1", "screen":"TOKEN2"}'></openvidu-webcomponent>
	 *
	 *
	 * @example
	 * <openvidu-webcomponent tokens='TOKEN1'></openvidu-webcomponent>
	 *
	 */
	@Input('tokens')
	set tokens(value: TokenModel | string) {
		// console.debug('Webcomponent tokens: ', value);
		try {
			this._tokens = this.castToJson(value);
			this.success = !!this._tokens?.webcam && !!this._tokens?.screen;
		} catch (error) {
			if (typeof value === 'string' && value !== '') {
				console.debug('Single token received.');
				this._tokens = { webcam: value };
				this.success = true;
			} else {
				console.error(error);
				console.error('Tokens parameter received is incorrect: ', value);
				console.error('Session cannot start');
			}
		}
	}

	/**
	 * @internal
	 */
	_onJoinButtonClicked() {
		this.onJoinButtonClicked.emit();
	}

	/**
	 * @internal
	 */
	_onToolbarLeaveButtonClicked() {
		this.success = false;
		this.onToolbarLeaveButtonClicked.emit();
	}

	/**
	 * @internal
	 */
	_onToolbarCameraButtonClicked() {
		this.onToolbarCameraButtonClicked.emit();
	}

	/**
	 * @internal
	 */
	_onToolbarMicrophoneButtonClicked() {
		this.onToolbarMicrophoneButtonClicked.emit();
	}
	/**
	 * @internal
	 */
	_onToolbarScreenshareButtonClicked() {
		this.onToolbarScreenshareButtonClicked.emit();
	}
	/**
	 * @internal
	 */
	_onToolbarParticipantsPanelButtonClicked() {
		this.onToolbarParticipantsPanelButtonClicked.emit();
	}
	/**
	 * @internal
	 */
	_onToolbarChatPanelButtonClicked() {
		this.onToolbarChatPanelButtonClicked.emit();
	}

	_onToolbarActivitiesPanelButtonClicked() {
		this.onToolbarActivitiesPanelButtonClicked.emit();
	}
	/**
	 * @internal
	 */
	_onToolbarFullscreenButtonClicked() {
		this.onToolbarFullscreenButtonClicked.emit();
	}
	onStartRecordingClicked(from: string) {
		if (from === 'toolbar') {
			this.onToolbarStartRecordingClicked.emit();
		} else if (from === 'panel') {
			this.onActivitiesPanelStartRecordingClicked.emit();
		}
	}

	/**
	 * @internal
	 */
	onStopRecordingClicked(from: string) {
		if (from === 'toolbar') {
			this.onToolbarStopRecordingClicked.emit();
		} else if (from === 'panel') {
			this.onActivitiesPanelStopRecordingClicked.emit();
		}
	}

	/**
	 * @internal
	 */
	_onActivitiesDownloadRecordingClicked(recordingId: string) {
		this.onActivitiesPanelDownloadRecordingClicked.emit(recordingId);
	}

	/**
	 * @internal
	 */
	_onActivitiesDeleteRecordingClicked(recordingId: string) {
		this.onActivitiesPanelDeleteRecordingClicked.emit(recordingId);
	}

	/**
	 * @internal
	 */
	_onSessionCreated(session: Session) {
		this.onSessionCreated.emit(session);
	}

	/**
	 * @internal
	 */
	_onParticipantCreated(participant: ParticipantAbstractModel) {
		this.onParticipantCreated.emit(participant);
	}

	disconnect() {
		this.openviduService.disconnect();
	}

	private castToBoolean(value: string | boolean): boolean {
		if (typeof value === 'boolean') {
			return value;
		} else if (typeof value === 'string') {
			if (value !== 'true' && value !== 'false') {
				throw new Error('Parameter has an incorrect string value.');
			}
			return value === 'true';
		} else {
			throw new Error('Parameter has not a valid type. The parameters must to be string or boolean.');
		}
	}

	private castToJson(value: TokenModel | string) {
		if (typeof value === 'string') {
			try {
				return JSON.parse(value);
			} catch (error) {
				throw 'Unexpected JSON' + error;
			}
		} else if (typeof value === 'object') {
			return value;
		} else {
			throw new Error(
				'Parameter has not a valid type. The parameters must to be string or TokenModel {webcam:string, screen: string}.'
			);
		}
	}

	private castToArray(value: CaptionsLangOption [] | string) {
		if (typeof value === 'string') {
			try {
				return JSON.parse(value);
			} catch (error) {
				throw 'Unexpected JSON' + error;
			}
		} else if (typeof value === 'object' && value.length > 0) {
			return value;
		} else {
			throw new Error(
				'Parameter has not a valid type. The parameters must to be string or CaptionsLangOptions [] [{name:string, ISO: string}].'
			);
		}
	}
}


text:
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - || die "Unable to install NodeJS 6.x."
sudo apt-get install nodejs
sudo ln -s "$(which nodejs)" /usr/bin/node

redpajama_set_name: RedPajamaGithub


text:
<?php

$loader = require __DIR__ . '/../vendor/autoload.php';

$basedir = realpath(__DIR__.'/..');
$loader->addPsr4('PhpGuard\\Plugins\\PhpSpec\\Functional\\', $basedir.'/functional');
$loader->register();


text:
title:  "Timing attack on arduino"
author: eax
date:   2015-04-10 14:00:00
tags:
- reverse
- hardware
- electronic
- side channel
- timing attack

---

I like Side Channels Attacks. It's a way to gather some information about your target (software, hardware device, web site) by a way (the channel) not directly related with the primary task of your target. These channels are unintentional consequences, or artifact, of the primary task.

## Let's give some examples.

You are in the same room as your target. The person is writing some text on his laptop and you want to know what it is. With a microphone, you record the audio for a couple of minutes. Guess what? We can use the noise made by pushing keys on a keyboard to recover what is being typed.
Here, the primary task of your keyboard is to allow you to type text. The noise made by typing on it is an unintentional consequence.

Every year a secret party is happening between some cool people you want to meet. Only the ones with the password can enter. And... You don't have this password. The good thing is that the host have a very bad memory, so just behind the front door, a screen has been hang up to display the party password in large black letters. Guess what? Screens are emitting electromagnetic leakage that can allow you to reconstruct the displayed image behind the door with some cheap device and some programming skills.
Here again, the electromagnetic radiation are artifact of the image being displayed.

## Overview

In this post, I will explain a basic side channel attack: Timing attack.
In Time attack, the channel that leak information is the time necessary to accomplish a task.

Let's imagine some door keypad:

 * The password is 6 digits long.
 * There is no "Enter key", the password is checked as soon as 6 keys has been pressed
 * Each key press make a led blink
 * When the password is wrong, a red led light up.
 * There is no trial limitation

How does it work? Well, we will assume that each key press is added on a buffer, and when the six digits has been typed, a routine is called to check this password against the one stored in memory. If this is the good password, the door unlock, otherwise, a red led blink.

## Assuming

We will assume that the check routine look like this:

```c
int check(char *input)
{
  int i;

  for (i = 0 ; i < 6 ; i++)
    if (input[i] != in_memory_password[i])
      return 0;
  return 1;
}
```

The C version is too high level to known exactly what will happen. So there is an ASM version of it: (AVR)

{% highlight asm linenos %}
ldi	r30, 0x09
ldi	r31, 0x01
movw	r26, r24
ld	r19, X+
movw	r24, r26
ld	r18, Z+
cpse	r19, r18    # Compare, Skip if Equal
rjmp	.+14		# jmp to line 16
ldi	r27, 0x01
cpi	r30, 0x0F
cpc	r31, r27
brne	.-20		# if eaqual, jmp to line 3
ldi	r24, 0x01
ldi	r25, 0x00
ret
ldi	r24, 0x00
ldi	r25, 0x00
ret
{% endhighlight %}

Let's see what happen if the password is 424344 and you enter 123456:

After 7 instructions, the first comparison occur:

{% highlight asm linenos linenostart=7 %}
cpse    r19, r18 # Compare, Skip if Equal
rjmp	.+14       # jmp to line 16
{% endhighlight %}

If the registers are equal, the next instruction is skipped. Here `r18` contain '4' and `r19` contain '1'. So the next instruction is not skipped and we jump at line 16. We set the return registers to 0 and return.

With a bad password, 11 instructions have been executed on the routine.
Now if we have only the first character good, the `rjmp` is skipped, and 9 more instructions are executed before the next `cpse`, and so one.

| Number of good characters|Number of instructions|
| -------------------------+---------------------|
| 0|11|
| 1|20|
| 2|29|
| 3|38|
| 4|47|
| 5|56|
| 6|68|

Last row is 68 and not 65 because there is 3 more instructions to do if it's the good password.
Okay, so more instruction mean more time, here his our time attack! Let's take a timer and measure it! Well... Kind of.

## Demo time!

To simulate the system, I used an arduino. I didn't have a keypad, so I just use the serial input from the computer. And as a timer, let's use an oscilloscope.

Here is the C++ code:

```c++
const char *in_memory_password = "424344";
const int led_pin = 13;

void setup() {
  Serial.begin(9600);
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, LOW);
}

int check(char *input)
{
  int i;

  for (i = 0 ; i < 6 ; i++)
    if (input[i] != in_memory_password[i])
      return 0;
  return 1;
}

void loop() {
  char buf[32];
  int r;

  Serial.setTimeout(10);
  while (!Serial.available())
    delay(10);
  r = Serial.readBytes(buf, 31);
  buf[r] = 0;

  digitalWrite(led_pin, HIGH);
  r = check(buf);
  digitalWrite(led_pin, LOW);

  if (r)
    Serial.println("Good password");
  else
    Serial.println("Wrong password");
}
```

For the demo, a led is turned on before the check function, and turned off just after.
It's just to be simpler, but it could have been done with a beep on each key + a beep after the check.

To measure the time needed for the check function, I just hook up a probe on the pin 13 (led).

We said earlier than the password is 424344.
This is what we can see when we type 123456:

![input: 123456](/assets/2015-04-06-timing-attack-on-arduino/1.png)

Here the first comparison fail, and these 6.48us are corresponding to the 11 instructions. (Actually more since the code to turn on/off the led is consuming some time too)

So what happen if the first character of the input correspond to the one in the password?

![input: 400000](/assets/2015-04-06-timing-attack-on-arduino/4.png)

Ok so now, it take 0.8us more than the previous input. We guessed our first character!

Ok, yes, we knew the password, so there is no fun.

This time, let have a python script sending USBTMC command to the oscilloscope and talk in serial with the arduino to bruteforce the password!

Sound a little bit funnier now, right?

```python
#!/usr/bin/env python3

import string
import numpy
import serial
import matplotlib.pyplot as plot
import itertools
import instrument
from multiprocessing import Process, Queue
import time

timescale = 2.e-06
timeoffset = 10.e-06
vscale = 2
trig_lvl = 4

o = instrument.RigolScope("/dev/usbtmc0")

def setup_oscilo():
    o.write(":TIM:SCAL %f" % timescale)
    o.write(":TIM:OFFS %f" % timeoffset)
    o.write(":CHAN1:SCAL %f" % vscale)
    o.write(":TRIG:EDG:SOUR CHAN1")
    o.write(":TRIG:EDG:LEV %d" % trig_lvl)

def single_triger():
    o.write(":SINGLE")
    while o.wr(":TRIG:STAT?", 20) != b"WAIT\n":
        time.sleep(0.1)

def mesure_time(q):
    while o.wr(":TRIG:STAT?", 20) != b"STOP\n":
        time.sleep(0.1)
    o.write(":WAV:POIN:MODE NOR")
    o.write(":WAV:DATA? CHAN1")
    rawdata = o.read(9000)

    data = numpy.frombuffer(rawdata, 'B')
    l = len(data)
    data = data - (16.*8)

    # It should be 16 (nb of division on the scope).
    # But 12 works better I don't known why...
    data /= 12.

    elem_high = [x for x in filter(lambda x: x > trig_lvl, data)]
    res = len(elem_high)/50.
    q.put(res)

if __name__ == "__main__":
    sr = serial.Serial('/dev/ttyUSB0', 9600)
    setup_oscilo()

    pwd = ""
    last = ""
    while last != b"Good password":
        longest = (None, -1)

        for c in string.digits:
            print("Trying [%s]" % (pwd + c))

            q = Queue()
            p = Process(target=mesure_time, args=(q,))
            single_triger()
            sr.write(bytes(pwd + c, "utf8"))
            p.start()

            res = q.get()
            print("Time: %f" % res)
            if res > longest[1]:
                longest = (c, res)
            p.join()
            last = sr.readline().strip()
            if last == b"Good password":
                break

        pwd += longest[0]

    print("Found password! [%s]" % pwd)
```
(You can find the instrument class in the links section bellow)

Enjoy the password cracking:

[![asciicast](https://asciinema.org/a/18588.png)](https://asciinema.org/a/18588)

Only 55 try and 26 second and your in!

For the record, there is the screen for each step:

100000:

![input: 1](/assets/2015-04-06-timing-attack-on-arduino/1.png)

400000:

![input: 4](/assets/2015-04-06-timing-attack-on-arduino/4.png)

420000:

![input: 42](/assets/2015-04-06-timing-attack-on-arduino/42.png)[![asciicast](https://asciinema.org/a/18586.png)](https://asciinema.org/a/18586)

424000:

![input: 424](/assets/2015-04-06-timing-attack-on-arduino/424.png)

424300:

![input: 4243](/assets/2015-04-06-timing-attack-on-arduino/4243.png)

424340:

![input: 42434](/assets/2015-04-06-timing-attack-on-arduino/42434.png)

424344:

![input: 424344](/assets/2015-04-06-timing-attack-on-arduino/424344.png)

It was my introduction to side channel attack and particularly to time attack. I might do other post on side channel. Maybe about power analysis on this exact same code.

## Links

- [RSA Key Extraction via Low-Bandwidth Acoustic Cryptanalysis](http://www.cs.tau.ac.il/~tromer/papers/acoustic-20131218.pdf)
- [DEF CON 21 - Melissa Elliott - Noise Floor Exploring Unintentional Radio Emissions](https://www.youtube.com/watch?v=5N1C3WB8c0o)
- [Defcon 17 - Sniff Keystrokes With Lasers/Voltmeters - Side Channel Attacks Using Optical Sampling](https://www.youtube.com/watch?v=9zq9DQAbWmU)
- [python rigole oscilloscope](http://www.cibomahto.com/2010/04/controlling-a-rigol-oscilloscope-using-linux-and-python/)


text: module.exports = require('./build/core').init


text:
<!doctype html>

    {% load mezzanine_tags i18n future staticfiles %}

    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width">
    <meta name="keywords" content="{% block meta_keywords %}{% endblock %}">
    <meta name="description" content="{% block meta_description %}{% endblock %}">
    <title>{% block meta_title %}{% endblock %}{% if settings.SITE_TITLE %}{{ settings.SITE_TITLE }}{% endif %}</title>
    <link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico">

<link href="http://libs.baidu.com/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
<link href="http://cdn.bootcss.com/twitter-bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet">

{% compress css %}

<link rel="stylesheet" href="{{ STATIC_URL }}css/mezzanine.css">

<link rel="stylesheet" href="{{ STATIC_URL }}css/drum.css">
<link rel="stylesheet" href="{{ STATIC_URL }}css/index.css">

{% endcompress %}

{% compress js %}

{% endcompress %}

{% block extra_head %}{% endblock %}

{% include "include/headernav.html" %}
{% comment %}

{% block breadcrumb %}

首页 /

{% endblock breadcrumb %}

{% endcomment %}

{% nevercache %}
{% for message in messages %}

    ×
    {{ message }}

{% endfor %}
{% endnevercache %}

{% block title %}{% endblock %}

{% block main %}{% endblock %}

{% include "include/right_nav.html" %}

power by wwj & ymj

    {% include "include/baidufenxi.html" %}


text:
package org.spongepowered.api.event.entity.living.human.fishing;

/**
 * Called when a {@link org.spongepowered.api.entity.living.Human} casts
 * a fishing line.
 */
public interface HumanCastFishingLineEvent extends HumanFishEvent {

    /**
     * Checks if this is a flowerpot.
     *
     * @return Whether this is a flowerpot
     */
    boolean isFlowerPot();
}


text:
<!DOCTYPE html>

    <title>{% if page.title %}{{ page.title }} – {% endif %}{{ site.name }} – {{ site.description }}</title>

    {% include meta.html %}

    <link rel="stylesheet" type="text/css" href="{{ site.baseurl }}/style.css" />
    <link rel="alternate" type="application/rss+xml" title="{{ site.name }} - {{ site.description }}" href="{{ site.baseurl }}/feed.xml" />

{{ site.name }}

{{ site.description }}

            Blog
            About

      {{ content }}

© Hiufan

    {% include analytics.html %}


text:
var colinApp = angular.module('colinApp.navController', ['ngRoute'])

.controller('navController', function($scope, $location, $ngRoute) {

	$log.log($routeParams);

});


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="shortcut icon" type="image/x-icon" href="/assets/images/favicon.png">

    <title>Open Source Projects</title>
    <meta name="description"
          content="个人技术博客">

    <link rel="canonical" href="http://localhost:4000/open-source.html">
    <link rel="alternate" type="application/rss+xml" title="生命不息  编程不止" href="http://localhost:4000/feed.xml">

    <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="/bower_components/octicons/octicons/octicons.css">
    <link rel="stylesheet" href="/bower_components/hover/css/hover-min.css">
    <link rel="stylesheet" href="/bower_components/primer-markdown/dist/user-content.min.css">
    <link rel="stylesheet" href="/assets/css/syntax.css">

    <link rel="stylesheet" href="/assets/css/common.css">

    <link rel="stylesheet" href="/assets/css/open-source.css">

             codeaftercode

                Home

                Open-Source

                Blog

                Bookmark

                About

Open Source Projects

                    I have  projects on Github

            Power by Yummy Jekyll

            TOP


text:
//================================================================
#pragma once

#ifndef CLASSEX_H
#define CLASSEX_H

#include <windows.h>
#include "tim.h"

_TIM_BEGIN

class ClassEx : public WNDCLASSEX
{
public:
	ClassEx(){
		::RtlSecureZeroMemory(&(*this), sizeof(WNDCLASSEX));
	}
	ClassEx(HINSTANCE hInst, LPCTSTR clsName, UINT iconID, UINT menuID, WNDPROC proc)
	{
		::RtlSecureZeroMemory(&(*this), sizeof(WNDCLASSEX));

		hInstance = hInst;
		lpszClassName = clsName;
		hbrBackground = HBRUSH(COLOR_WINDOW+1);
		hCursor = LoadCursor(NULL, IDC_ARROW);
		cbSize = sizeof(WNDCLASSEX);
		hIcon = iconID == 0 ? NULL : LoadIcon(hInst, MAKEINTRESOURCE(iconID));
		style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
		lpszMenuName = menuID == 0 ? NULL : MAKEINTRESOURCE(menuID);
		lpfnWndProc = proc;
	}
	~ClassEx(){}

	void setClassName(LPCTSTR lpClsName){
		lpszClassName = lpClsName;
	}
	void setIcon(HICON hicon){
		hIcon = hicon;
	}
	void setIcon(UINT uId){
		hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(uId));
	}

	void setMenu(UINT uId){
		lpszMenuName = MAKEINTRESOURCE(uId);
	}
	void setMenu(LPCTSTR lpMenuName){
		lpszMenuName = lpMenuName;
	}
	void setStyle(UINT uStyle){
		style = uStyle;
	}
	void setBkBrush(HBRUSH hbr){
		hbrBackground = hbr;
	}
	bool Register()	{	return RegisterClassEx(&*this) ? true : false;	}
};

_TIM_END

#endif


text:
<?php

namespace app\framework\Component\Route\Klein;

use BadMethodCallException;
use app\framework\Component\Route\Klein\Exceptions\DuplicateServiceException;
use app\framework\Component\Route\Klein\Exceptions\UnknownServiceException;

/**
 * App
 */
class App
{

    /**
     * Class properties
     */

    /**
     * The array of app services
     *
     * @type array
     */
    protected $services = array();

    /**
     * Magic "__get" method
     *
     * Allows the ability to arbitrarily request a service from this instance
     * while treating it as an instance property
     *
     * This checks the lazy service register and automatically calls the registered
     * service method
     *
     * @param string $name              The name of the service
     * @throws UnknownServiceException  If a non-registered service is attempted to fetched
     * @return mixed
     */
    public function __get($name)
    {
        if (!isset($this->services[$name])) {
            throw new UnknownServiceException('Unknown service '. $name);
        }
        $service = $this->services[$name];

        return $service();
    }

    /**
     * Magic "__call" method
     *
     * Allows the ability to arbitrarily call a property as a callable method
     * Allow callbacks to be assigned as properties and called like normal methods
     *
     * @param callable $method          The callable method to execute
     * @param array $args               The argument array to pass to our callback
     * @throws BadMethodCallException   If a non-registered method is attempted to be called
     * @return void
     */
    public function __call($method, $args)
    {
        if (!isset($this->services[$method]) || !is_callable($this->services[$method])) {
            throw new BadMethodCallException('Unknown method '. $method .'()');
        }

        return call_user_func_array($this->services[$method], $args);
    }

    /**
     * Register a lazy service
     *
     * @param string $name                  The name of the service
     * @param callable $closure             The callable function to execute when requesting our service
     * @throws DuplicateServiceException    If an attempt is made to register two services with the same name
     * @return mixed
     */
    public function register($name, $closure)
    {
        if (isset($this->services[$name])) {
            throw new DuplicateServiceException('A service is already registered under '. $name);
        }

        $this->services[$name] = function () use ($closure) {
            static $instance;
            if (null === $instance) {
                $instance = $closure();
            }

            return $instance;
        };
    }
}


text:
<!DOCTYPE html>

  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">

<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />

  <link href="//cdn.jsdelivr.net/fancybox/2.1.5/jquery.fancybox.min.css" rel="stylesheet" type="text/css" />

<link href="https://cdn.bootcss.com/font-awesome/4.6.2/css/font-awesome.min.css" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.3" rel="stylesheet" type="text/css" />

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.3">

  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.ico?v=5.1.3">

  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.ico?v=5.1.3">

  <link rel="mask-icon" href="/images/logo.svg?v=5.1.3" color="#222">

  <meta name="keywords" content="数据库,Oracle," />

<meta name="description" content="Oracle数据库服务总结Oracle的数据库服务默认有5个看了几篇文章后,总结其作用如下:1 .OracleServiceORCL:数据库服务,这个服务会自动的启动和停止数据库。ORCL是Oracle的实例标识。此服务被默认的设置为开机启动。  必须启动,这是Oracle数据库的服务。  2 .OracleOraDb11g_home1TNSListener.监听器服务,服务只有在数据库需要远程访">
<meta name="keywords" content="数据库,Oracle">
<meta property="og:type" content="article">
<meta property="og:title" content="Oracle数据库服务总结">
<meta property="og:url" content="https://www.hyhcoder.com/2014/05/15/Oracle数据库服务总结/index.html">
<meta property="og:site_name" content="hyhcoder的博客">
<meta property="og:description" content="Oracle数据库服务总结Oracle的数据库服务默认有5个看了几篇文章后,总结其作用如下:1 .OracleServiceORCL:数据库服务,这个服务会自动的启动和停止数据库。ORCL是Oracle的实例标识。此服务被默认的设置为开机启动。  必须启动,这是Oracle数据库的服务。  2 .OracleOraDb11g_home1TNSListener.监听器服务,服务只有在数据库需要远程访">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2017-06-18T08:55:42.903Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Oracle数据库服务总结">
<meta name="twitter:description" content="Oracle数据库服务总结Oracle的数据库服务默认有5个看了几篇文章后,总结其作用如下:1 .OracleServiceORCL:数据库服务,这个服务会自动的启动和停止数据库。ORCL是Oracle的实例标识。此服务被默认的设置为开机启动。  必须启动,这是Oracle数据库的服务。  2 .OracleOraDb11g_home1TNSListener.监听器服务,服务只有在数据库需要远程访">

  <link rel="canonical" href="https://www.hyhcoder.com/2014/05/15/Oracle数据库服务总结/"/>

  <title>Oracle数据库服务总结 | hyhcoder的博客</title>

        hyhcoder的博客

Stay hungry stay foolish

    <button>

    </button>

            首页

            标签

            归档

            关于

            搜索

      <input autocomplete="off"
             placeholder="搜索..." spellcheck="false"
             type="text" id="local-search-input">

    <link itemprop="mainEntityOfPage" href="https://www.hyhcoder.com/2014/05/15/Oracle数据库服务总结/">

      <meta itemprop="name" content="hyhcoder">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="https://img.hyhcoder.top/avatar.jpg">

      <meta itemprop="name" content="hyhcoder的博客">

Oracle数据库服务总结

                发表于

              <time title="创建于" itemprop="dateCreated datePublished" datetime="2014-05-15T16:28:56+09:00">
                2014-05-15
              </time>

Oracle数据库服务总结

Oracle的数据库服务默认有5个

看了几篇文章后,总结其作用如下:
1 .OracleServiceORCL:数据库服务,这个服务会自动的启动和停止数据库。ORCL是Oracle的实例标识。此服务被默认的设置为开机启动。

必须启动,这是Oracle数据库的服务。

2 .OracleOraDb11g_home1TNSListener.监听器服务,服务只有在数据库需要远程访问的时候才需要,此服务被默认的设置为开机启动。

必须启动,这是临听,用于远程客户端连接你的Oracle;

3 .OracleJobSchedulerORCL.Oracle作业调度服务,ORCL是Oracle实例标识。此服务被默认设置为禁用状态.

通常不启动,用于定期操作任务的服务;

数据库工作日程调度,一般没有安排工作日程就不需要启动,为什么默认是禁用?因为启动后会占用很大的系统资源。

4 . OracleDBConsoleorcl.Oracle数据库控制台服务,orcl是Oracle的实例标识,默认的实例为orcl.在运行Enterprise Manager 的时候,需要启动这个服务。此服务被默认设置为自动开机启动的。

可以不启动,用于管理Oracle的企业管理器的服务;

5 .OracleOraDb10g_home1iSQLPlus iSQLPlus的服务进程

可以不启动,这是isqlplus服务,用于用网页执行sql执行,11g已经取消了这个功能;

用命令启动

启动listener:lsnrctl start

启动数据库:net start OracleServiceORCL

特别注意

在资源不够的情况下,要记得:
只有这两项是必须启动的:OracleOraDb10g_home1TNSListener和OracleServiceORCL。(就是监听和数据库服务)

对上面的服务也可以做一个批处理文件来启动和停止,批处理文件如下:

建立dbstart.cmd文件(开启)

添加如下内容:

1
2
3
4
5
6

@echo off
net  start  OracleServiceORACLE
net  start  OracleDBConsoleoracle
net  start  OracleOraDb10g_home1iSQL*Plus
net  start  OracleOraDb10g_home1TNSListener
pause

同样我们可以建立关闭文件(dbstop.cmd)

1
2
3
4
5
6

@echo off
net  stop  OracleServiceORACLE
net  stop  OracleDBConsoleoracle
net  stop  OracleOraDb10g_home1iSQL*Plus
net  stop  OracleOraDb10g_home1TNSListener
pause

扫码关注我的个人订阅号

            # 数据库,Oracle

                 Oracle中删除重复记录整理

                关于Java中转换机制整理

            文章目录

            站点概览

hyhcoder

From zero to infinity

                  43
                  日志

                  13
                  标签

                      GitHub

                      Google

                      E-Mail

1. Oracle数据库服务总结

1.1. Oracle的数据库服务默认有5个

1.2. 用命令启动

1.3. 特别注意

© 2014 — 2019

  hyhcoder

Hosted by Coding Pages

      本站访客数

      人次

      本站总访问量

      次

        <link rel="stylesheet" href="https://img.hyhcoder.top/static/gitment.css">


text:
<?php

namespace GM\CookiePolicy;

/**
 * @author  Giuseppe Mazzapica <giuseppe.mazzapica@gmail.com>
 * @license http://opensource.org/licenses/MIT MIT
 * @package gm-cookie-policy
 */
class Config implements \ArrayAccess
{
    const OPTION = 'gm-cookie-policy';
    const CAP    = 'manage_options';

    /**
     * @var \ArrayObject
     */
    private $stored;

    /**
     * @var \ArrayObject
     */
    private $live;

    /**
     * @param \GM\CookiePolicy\Config $config
     * @param array                   $newData
     * @return \GM\CookiePolicy\Config
     */
    public static function newInstanceFrom(Config $config = null, array $newData = [])
    {
        $live = $config ? $config->live->getArrayCopy() : [];
        $stored = $config ? array_merge($config->stored->getArrayCopy(), $newData) : $newData;
        $instance =  new static($live, []);
        $instance->stored = new \ArrayObject($stored);

        return $instance;
    }

    /**
     * @param array $liveConfig
     * @param array $defaults
     */
    public function __construct(array $liveConfig = [], array $defaults = [])
    {
        $stored = get_option(self::OPTION) ?: [];
        $this->stored = new \ArrayObject(array_merge($defaults, $stored));
        $liveConfig['capability'] = apply_filters('cookie-policy.config-capability', self::CAP);
        $this->live = new \ArrayObject($liveConfig);
    }

    /**
     * @return array
     */
    public function toArray()
    {
        return array_merge($this->stored->getArrayCopy(), $this->live->getArrayCopy());
    }

    /**
     * @return bool
     */
    public function save()
    {
        if (! is_admin() || ! current_user_can($this->live['capability'])) {
            return false;
        }

        $now =  get_option(self::OPTION, []);
        if ($now === $this->stored->getArrayCopy()) {
            return true;
        }

        return update_option(self::OPTION, $this->stored->getArrayCopy(), 'no');
    }

    /**
     * @inheritdoc
     */
    public function offsetExists($offset)
    {
        return $this->stored->offsetExists($offset) || $this->live->offsetExists($offset);
    }

    /**
     * @inheritdoc
     */
    public function offsetGet($offset)
    {
        if (! $this->offsetExists($offset)) {
            throw new \BadMethodCallException($offset.' is not a valid config entry.');
        }

        return $this->stored->offsetExists($offset)
            ? $this->stored->offsetGet($offset)
            : $this->live->offsetGet($offset);
    }

    /**
     * @inheritdoc
     */
    public function offsetSet($offset, $value)
    {
        if ($this->offsetExists($offset)) {
            throw new \BadMethodCallException('Values in '.__CLASS__.' can\'t be modified.');
        }

        $this->stored->offsetSet($offset, $value);
    }

    /**
     * @inheritdoc
     */
    public function offsetUnset($offset)
    {
        throw new \BadMethodCallException('Values in '.__CLASS__.' can\'t be modified.');
    }
}


text:
{% extends 'server_ui/templates/base.html' %}
{% block title %}Confirm Vote{% endblock %}

{% block content %}

Your Vote was Cast

    A vote was successfully cast for {{voter.voter_id}}, with vote fingerprint:

    <tt style="font-size: 2em;">{{voter.vote_hash}}</tt>

    Visit the election homepage.

{% endblock %}


text:
package org.springframework.security.oauth2.config.annotation.web.configuration;

import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

/**
 *

 * @deprecated See the OAuth 2.0 Migration Guide for Spring Security 5.
 *
 * @author Dave Syer
 *
 */
@Deprecated
public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {

	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
	}

	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
	}

}


text:
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('api', '0016_auto_20150410_0738'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='problemcomment',
            name='raw_content',
        ),
        migrations.AlterField(
            model_name='problemcomment',
            name='content',
            field=models.TextField(default=''),
            preserve_default=False,
        ),
    ]


text:
Quickly open a URL in an [Electron](http://electron.atom.io) shell from your Terminal!

## Install

    npm install --global electron-open

## Use

    electron-open http://localhost:3000
    electron-open https://news.ycombinator.com

## Licence

ISC


text:
const cache = require('apicache')
  .options({
    headers: {
      'cache-control': 'no-cache'
    }
  })
  .middleware
const bodyParser = require('body-parser')
const express = require('express')
const controller = require('./controller')
const app = module.exports = express()

app.use(express.static('public'))
app.use(bodyParser.text())
app.get('/shows/:ids?', cache('6 hours'), controller.getAirDates)
app.post('/lists/', controller.createList)
app.get('/lists/:id', cache('6 hours'), controller.getList)
app.put('/lists/:id', controller.updateList)
app.delete('/lists/:id', controller.deleteList)
app.use(controller.errorHandler)

!module.parent && app.listen(process.env.PORT || 5000, function () {
  console.log('TVCal listening on port', this.address().port)
})


text:
Plugin.define "Newscoop" do
author "Brendan Coles <bcoles@gmail.com>" # 2012-05-09
version "0.1"
description "Open content management system for professional journalists & online newspapers."
website "http://www.sourcefabric.org/en/newscoop/"

# Google results as at 2012-04-10 #
# 49 for intitle:"Login" inurl:admin "Newscoop" "the open content management system for professional journalists."

# Dorks #
dorks [
'intitle:"Login" inurl:admin "Newscoop" "the open content management system for professional journalists."'
]

# Matches #
matches [

# /admin/ # Admin Page # Version Detection
{ :version=>/\s+Newscoop<\/a> ([\d\.]+)[^,]*,\s+the open content management system for professional journalists\./ },

# Powered by text
{ :text=>'Powered by Newscoop, the open content management system for professional journalists.
' },
{ :text=>'Powered by Newscoop, the open content management system for professional journalists.' },

# Meta Generator
{ :text=>'<meta name="generator" content="Newscoop" />' },

]

end


text:
'use strict';

var isZero = require('./isZero');
var subtraction = require('./../numerals/subtraction');

function isGreaterOrEqual(a) {
    return function(b) {
        return isZero(subtraction(b)(a));
    };
}

module.exports = isGreaterOrEqual;


text:
#ifndef WorkerScriptController_h
#define WorkerScriptController_h

#if ENABLE(WORKERS)

#include "V8Binding.h"

#include <v8.h>
#include <wtf/OwnPtr.h>
#include <wtf/Threading.h>

namespace WebCore {

    class ScriptSourceCode;
    class ScriptValue;
    class WorkerContext;
    class WorkerContextExecutionProxy;

    class WorkerScriptController {
    public:
        WorkerScriptController(WorkerContext*);
        ~WorkerScriptController();

        WorkerContextExecutionProxy* proxy() { return m_proxy.get(); }
        WorkerContext* workerContext() { return m_workerContext; }

        void evaluate(const ScriptSourceCode&);
        void evaluate(const ScriptSourceCode&, ScriptValue* exception);

        void setException(const ScriptValue&);

        // Async request to terminate a future JS execution. Eventually causes termination
        // exception raised during JS execution, if the worker thread happens to run JS.
        // After JS execution was terminated in this way, the Worker thread has to use
        // forbidExecution()/isExecutionForbidden() to guard against reentry into JS.
        // Can be called from any thread.
        void scheduleExecutionTermination();
        bool isExecutionTerminating() const;

        // Called on Worker thread when JS exits with termination exception caused by forbidExecution() request,
        // or by Worker thread termination code to prevent future entry into JS.
        void forbidExecution();
        bool isExecutionForbidden() const;

        void disableEval(const String&);

        // Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context.
        static WorkerScriptController* controllerForContext();

    private:
        WorkerContext* m_workerContext;
        OwnPtr<WorkerContextExecutionProxy> m_proxy;
        v8::Isolate* m_isolate;
        OwnPtr<DOMDataStore> m_domDataStore;
        bool m_executionForbidden;
        bool m_executionScheduledToTerminate;
        mutable Mutex m_scheduledTerminationMutex;
    };

} // namespace WebCore

#endif // ENABLE(WORKERS)

#endif // WorkerScriptController_h


text:
// NOTE - eventually this file will be automatically updated using a Perl script that understand
// the naming of test case files, functions, and namespaces.

#ifndef _TESTCASES_H
#define _TESTCASES_H

#ifdef __cplusplus
extern "C" {
#endif

// declare C good and bad functions
#ifndef OMITGOOD
	/* BEGIN-AUTOGENERATED-C-GOOD-FUNCTION-DECLARATIONS */

	/* END-AUTOGENERATED-C-GOOD-FUNCTION-DECLARATIONS */
#endif // OMITGOOD

#ifndef OMITBAD
	/* BEGIN-AUTOGENERATED-C-BAD-FUNCTION-DECLARATIONS */

	/* END-AUTOGENERATED-C-BAD-FUNCTION-DECLARATIONS */
#endif // OMITBAD

#ifdef __cplusplus
} // end extern "C"
#endif

#ifdef __cplusplus
// declare C++ namespaces and good and bad functions

#ifndef OMITGOOD
	/* BEGIN-AUTOGENERATED-CPP-GOOD-FUNCTION-DECLARATIONS */
	namespace CWE397_Throw_Generic_Exception__declare_dotdotdot_w32_01 { void good();}

	namespace CWE397_Throw_Generic_Exception__declare_exception_01 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_01 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_02 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_03 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_04 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_05 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_06 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_07 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_08 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_09 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_10 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_11 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_12 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_13 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_14 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_15 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_16 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_17 { void good();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_18 { void good();}

	/* END-AUTOGENERATED-CPP-GOOD-FUNCTION-DECLARATIONS */
#endif // OMITGOOD

#ifndef OMITBAD
	/* BEGIN-AUTOGENERATED-CPP-BAD-FUNCTION-DECLARATIONS */
	namespace CWE397_Throw_Generic_Exception__declare_dotdotdot_w32_01 { void bad();}

	namespace CWE397_Throw_Generic_Exception__declare_exception_01 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_01 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_02 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_03 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_04 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_05 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_06 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_07 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_08 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_09 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_10 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_11 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_12 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_13 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_14 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_15 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_16 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_17 { void bad();}

	namespace CWE397_Throw_Generic_Exception__throw_exception_18 { void bad();}

	/* END-AUTOGENERATED-CPP-BAD-FUNCTION-DECLARATIONS */
#endif // OMITBAD

#endif // __cplusplus

#endif //  _TESTCASES_H


text:
using Gmich.Cedrus.IOC;
using Gmich.Cedrus.Rendering;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;

namespace Gmich.Cedrus.TandrixClone.Layers
{
    internal class LayersModule : CendrusModule
    {
        public override void Register(IocBuilder builder)
        {
            builder.RegisterSingleton(c =>
                RenderingUtilities.CreateRenderTarget(c.Resolve<GraphicsDevice>(), 10, 10))
                .IdentifiedAs("background")
            .Register(c =>
                new Func<Color>(() => Color.White))
                .IdentifiedAs("backgroundColor")
            .RegisterSingleton<BackgroundLayerRenderer, BackgroundLayerRenderer>();

        }
    }
}


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="shortcut icon" href="../../assets/ico/favicon.ico">

    <title>Buzzword Bingo Generator</title>

    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
	<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">

Buzzword Bingo Generator

		<form role="form" style="width: 30%">

			Enter a series of buzzwords separated by newlines (for best results include at least 24)
			<textarea class="form-control" name="words" rows="10"></textarea>

			Number of cards to generate
			<input class="form-control" name="count" type="text">

		<button type="button" id="generate" class="btn btn-primary">Generate!</button>
		<button type="button" id="print" class="btn btn-primary disabled">Print</button>
		</form>


text:
#include <aws/mediaconvert/model/TrackSourceSettings.h>
#include <aws/core/utils/json/JsonSerializer.h>

#include <utility>

using namespace Aws::Utils::Json;
using namespace Aws::Utils;

namespace Aws
{
namespace MediaConvert
{
namespace Model
{

TrackSourceSettings::TrackSourceSettings() :
    m_trackNumber(0),
    m_trackNumberHasBeenSet(false)
{
}

TrackSourceSettings::TrackSourceSettings(JsonView jsonValue) :
    m_trackNumber(0),
    m_trackNumberHasBeenSet(false)
{
  *this = jsonValue;
}

TrackSourceSettings& TrackSourceSettings::operator =(JsonView jsonValue)
{
  if(jsonValue.ValueExists("trackNumber"))
  {
    m_trackNumber = jsonValue.GetInteger("trackNumber");

    m_trackNumberHasBeenSet = true;
  }

  return *this;
}

JsonValue TrackSourceSettings::Jsonize() const
{
  JsonValue payload;

  if(m_trackNumberHasBeenSet)
  {
   payload.WithInteger("trackNumber", m_trackNumber);

  }

  return payload;
}

} // namespace Model
} // namespace MediaConvert
} // namespace Aws


text:
from inspect import Parameter, Signature
import re
from collections import OrderedDict

class Descriptor:
    def __init__(self, name=None):
        self.name = name

    def __set__(self, instance, value):
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        raise AttributeError("Can't delete")

class Typed(Descriptor):
    ty = object
    def __set__(self, instance, value):
        if not isinstance(value, self.ty):
            raise TypeError('Expected %s' % self.ty)
        super().__set__(instance, value)

# Specialized types
class Integer(Typed):
    ty = int

class Float(Typed):
    ty = float

class String(Typed):
    ty = str

# Value checking
class Positive(Descriptor):
    def __set__(self, instance, value):
        if value < 0:
            raise ValueError('Expected >= 0')
        super().__set__(instance, value)

# More specialized types
class PosInteger(Integer, Positive):
    pass

class PosFloat(Float, Positive):
    pass

# Length checking
class Sized(Descriptor):
    def __init__(self, *args, maxlen, **kwargs):
        self.maxlen = maxlen
        super().__init__(*args, **kwargs)

    def __set__(self, instance, value):
        if len(value) > self.maxlen:
            raise ValueError('Too big')
        super().__set__(instance, value)

class SizedString(String, Sized):
    pass

# Pattern matching
class Regex(Descriptor):
    def __init__(self, *args, pat, **kwargs):
        self.pat = re.compile(pat)
        super().__init__(*args, **kwargs)

    def __set__(self, instance, value):
        if not self.pat.match(value):
            raise ValueError('Invalid string')
        super().__set__(instance, value)

class SizedRegexString(SizedString, Regex):
    pass

# Structure definition code

def make_signature(names):
    return Signature(
        Parameter(name, Parameter.POSITIONAL_OR_KEYWORD)
        for name in names)

class StructMeta(type):
    @classmethod
    def __prepare__(cls, name, bases):
        return OrderedDict()

    def __new__(cls, clsname, bases, clsdict):
        fields = [key for key, val in clsdict.items()
                  if isinstance(val, Descriptor) ]
        for name in fields:
            clsdict[name].name = name

        clsobj = super().__new__(cls, clsname, bases, dict(clsdict))
        sig = make_signature(fields)
        setattr(clsobj, '__signature__', sig)
        return clsobj

class Structure(metaclass=StructMeta):
    def __init__(self, *args, **kwargs):
        bound = self.__signature__.bind(*args, **kwargs)
        for name, val in bound.arguments.items():
            setattr(self, name, val)

if __name__ == '__main__':
    class Stock(Structure):
        name = SizedRegexString(maxlen=8, pat='[A-Z]+$')
        shares = PosInteger()
        price = PosFloat()


text:
/* this file has been autogenerated by vtkNodeJsWrap */
/* editing this might proof futile */

#ifndef NATIVE_EXTENSION_VTK_VTKINPUTSTREAMWRAP_H
#define NATIVE_EXTENSION_VTK_VTKINPUTSTREAMWRAP_H

#include <nan.h>

#include <vtkSmartPointer.h>
#include <vtkInputStream.h>

#include "vtkObjectWrap.h"
#include "../../plus/plus.h"

class VtkInputStreamWrap : public VtkObjectWrap
{
	public:
		using Nan::ObjectWrap::Wrap;
		static void Init(v8::Local<v8::Object> exports);
		static void InitPtpl();
		static void ConstructorGetter(
			v8::Local<v8::String> property,
			const Nan::PropertyCallbackInfo<v8::Value>& info);

		VtkInputStreamWrap(vtkSmartPointer<vtkInputStream>);
		VtkInputStreamWrap();
		~VtkInputStreamWrap( );
		static Nan::Persistent<v8::FunctionTemplate> ptpl;

	private:
		static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);

		static void EndReading(const Nan::FunctionCallbackInfo<v8::Value>& info);
		static void GetClassName(const Nan::FunctionCallbackInfo<v8::Value>& info);
		static void IsA(const Nan::FunctionCallbackInfo<v8::Value>& info);
		static void NewInstance(const Nan::FunctionCallbackInfo<v8::Value>& info);
		static void SafeDownCast(const Nan::FunctionCallbackInfo<v8::Value>& info);
		static void StartReading(const Nan::FunctionCallbackInfo<v8::Value>& info);

#ifdef VTK_NODE_PLUS_VTKINPUTSTREAMWRAP_CLASSDEF
		VTK_NODE_PLUS_VTKINPUTSTREAMWRAP_CLASSDEF
#endif
};

#endif


text:
                To(select campaign)
                {!! buildSelect(route('admin::campaign::get::json'), 'to', false, [], [], null, "select campaign listed clients") !!}

                Subject
                <input class="form-control" placeholder="Subject:">

            @include('admin.fileLinker.fileLinkerModal', [$btnMsg='choose email template', $preferredTag = "gallery", $fileTypes = 'document', $multiple = false, $outputElementPath = ".mail-output", $disk = "mails"])

                @include('admin.components.description-form', [$property_name='message'])

                     Attachment
                    <input type="file" name="attachment">

Max. 32MB

                <button type="button" class="btn btn-default"> Draft</button>
                <button type="submit" class="btn btn-primary"> Send</button>

            <button type="reset" class="btn btn-default pull-left"> Discard</button>

@push('scripts-add_on')

@endpush


text:
using System;

namespace Querify
{
    public class QuerifyException : Exception
    {
        public QuerifyException(string message)
            : base(message)
        {
        }
    }

    public class NoMatchFoundException : QuerifyException
    {
        public NoMatchFoundException(string message)
            : base(message)
        {
        }
    }
}


text:
package org.apache.camel.component.netty;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Arrays;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.impl.JndiRegistry;
import org.apache.camel.util.IOHelper;
import org.junit.Test;

/**
 *
 */
public class UnsharableCodecsConflictsTest extends BaseNettyTest {

    static final byte[] LENGTH_HEADER = {0x00, 0x00, 0x40, 0x00}; // 4096 bytes

    private Processor processor = new P();

    private int port1;
    private int port2;

    @Override
    protected JndiRegistry createRegistry() throws Exception {
        JndiRegistry registry = super.createRegistry();

        // we can share the decoder between multiple netty consumers, because they have the same configuration
        // and we use a ChannelHandlerFactory
        ChannelHandlerFactory decoder = ChannelHandlerFactories.newLengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4);
        registry.bind("length-decoder", decoder);
        registry.bind("length-decoder2", decoder);

        return registry;
    }

    @Test
    public void canSupplyMultipleCodecsToEndpointPipeline() throws Exception {
        byte[] sPort1 = new byte[8192];
        byte[] sPort2 = new byte[16383];
        Arrays.fill(sPort1, (byte) 0x38);
        Arrays.fill(sPort2, (byte) 0x39);
        byte[] bodyPort1 = (new String(LENGTH_HEADER) + new String(sPort1)).getBytes();
        byte[] bodyPort2 = (new String(LENGTH_HEADER) + new String(sPort2)).getBytes();

        MockEndpoint mock = getMockEndpoint("mock:result");
        mock.expectedBodiesReceived(new String(sPort2) + "9");

        Socket server1 = getSocket("localhost", port1);
        Socket server2 = getSocket("localhost", port2);

        try {
            sendSopBuffer(bodyPort2, server2);
            sendSopBuffer(bodyPort1, server1);
            sendSopBuffer(new String("9").getBytes(), server2);
        } catch (Exception e) {
            log.error("", e);
        } finally {
            server1.close();
            server2.close();
        }

        mock.assertIsSatisfied();
    }

    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            public void configure() throws Exception {
                port1 = getPort();
                port2 = getNextPort();

                from("netty:tcp://localhost:" + port1 + "?decoder=#length-decoder&sync=false")
                        .process(processor);

                from("netty:tcp://localhost:" + port2 + "?decoder=#length-decoder2&sync=false")
                        .process(processor)
                        .to("mock:result");
            }
        };
    }

    private static Socket getSocket(String host, int port) throws IOException {
        Socket s = new Socket(host, port);
        s.setSoTimeout(60000);
        return s;
    }

    public static void sendSopBuffer(byte[] buf, Socket server) throws Exception {
        BufferedOutputStream dataOut = IOHelper.buffered(server.getOutputStream());
        try {
            dataOut.write(buf, 0, buf.length);
            dataOut.flush();
        } catch (Exception e) {
            IOHelper.close(dataOut);
            server.close();
            throw e;
        }
    }

    class P implements Processor {

        @Override
        public void process(Exchange exchange) throws Exception {
            exchange.getOut().setBody(exchange.getIn().getBody(String.class));
        }
    }

}